up
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Node.Internal;
|
||||
|
||||
internal static class NodeEnvironmentScanner
|
||||
{
|
||||
private static readonly Regex EnvAssign = new("^\s*(ENV|ARG)\s+NODE_OPTIONS\s*(=|\s)(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public static IReadOnlyList<LanguageComponentRecord> Scan(LanguageAnalyzerContext context, IReadOnlyList<string> sourceRoots, CancellationToken cancellationToken)
|
||||
{
|
||||
var warnings = new List<LanguageComponentRecord>();
|
||||
|
||||
foreach (var root in sourceRoots)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var dockerfile = Path.Combine(root, "Dockerfile");
|
||||
if (File.Exists(dockerfile))
|
||||
{
|
||||
warnings.AddRange(ScanDockerfile(context, dockerfile));
|
||||
}
|
||||
|
||||
var envFile = Path.Combine(root, ".env");
|
||||
if (File.Exists(envFile))
|
||||
{
|
||||
warnings.AddRange(ScanEnvFile(context, envFile));
|
||||
}
|
||||
}
|
||||
|
||||
return warnings
|
||||
.OrderBy(static r => r.ComponentKey, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static IEnumerable<LanguageComponentRecord> ScanDockerfile(LanguageAnalyzerContext context, string dockerfile)
|
||||
{
|
||||
try
|
||||
{
|
||||
var lines = File.ReadAllLines(dockerfile);
|
||||
for (var i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var match = EnvAssign.Match(lines[i]);
|
||||
if (!match.Success)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var value = match.Groups["value"].Value.Trim().Trim('"', '\'');
|
||||
yield return BuildWarning(context, dockerfile, i + 1, value, source: "Dockerfile", reason: "NODE_OPTIONS");
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<LanguageComponentRecord> ScanEnvFile(LanguageAnalyzerContext context, string envFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
var lines = File.ReadAllLines(envFile);
|
||||
for (var i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (!line.Contains("NODE_OPTIONS", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var parts = line.Split('=', 2);
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var value = parts[1].Trim().Trim('"', '\'');
|
||||
yield return BuildWarning(context, envFile, i + 1, value, source: ".env", reason: "NODE_OPTIONS");
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
private static LanguageComponentRecord BuildWarning(LanguageAnalyzerContext context, string filePath, int lineNumber, string value, string source, string reason)
|
||||
{
|
||||
var locator = context.GetRelativePath(filePath).Replace(Path.DirectorySeparatorChar, '/');
|
||||
var metadata = new List<KeyValuePair<string, string?>>
|
||||
{
|
||||
new("source", source),
|
||||
new("locator", string.Concat(locator, "#", lineNumber.ToString(CultureInfo.InvariantCulture))),
|
||||
new("reason", reason),
|
||||
new("value", value)
|
||||
};
|
||||
|
||||
var evidence = new[]
|
||||
{
|
||||
new LanguageComponentEvidence(
|
||||
LanguageEvidenceKind.Metadata,
|
||||
"node.env",
|
||||
string.Concat(locator, "#", lineNumber.ToString(CultureInfo.InvariantCulture)),
|
||||
value,
|
||||
null)
|
||||
};
|
||||
|
||||
return LanguageComponentRecord.FromExplicitKey(
|
||||
analyzerId: "node",
|
||||
componentKey: string.Concat("warning:node-options:", locator, "#", lineNumber.ToString(CultureInfo.InvariantCulture)),
|
||||
purl: null,
|
||||
name: "NODE_OPTIONS warning",
|
||||
version: null,
|
||||
type: "node:warning",
|
||||
metadata: metadata,
|
||||
evidence: evidence,
|
||||
usedByEntrypoint: false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user