notify doctors work, audit work, new product advisory sprints
This commit is contained in:
@@ -426,8 +426,13 @@ function flush() {
|
||||
const sorted = events.sort((a, b) => {
|
||||
const at = String(a.ts);
|
||||
const bt = String(b.ts);
|
||||
if (at === bt) return String(a.type).localeCompare(String(b.type));
|
||||
return at.localeCompare(bt);
|
||||
if (at === bt) {
|
||||
const atype = String(a.type);
|
||||
const btype = String(b.type);
|
||||
if (atype === btype) return 0;
|
||||
return atype < btype ? -1 : 1;
|
||||
}
|
||||
return at < bt ? -1 : 1;
|
||||
});
|
||||
|
||||
const data = sorted.map((e) => JSON.stringify(e)).join("\\n");
|
||||
|
||||
@@ -11,11 +11,12 @@ internal sealed class DenoRuntimeTraceRecorder
|
||||
private readonly string _rootPath;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public DenoRuntimeTraceRecorder(string rootPath, TimeProvider? timeProvider = null)
|
||||
public DenoRuntimeTraceRecorder(string rootPath, TimeProvider timeProvider)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(rootPath);
|
||||
ArgumentNullException.ThrowIfNull(timeProvider);
|
||||
_rootPath = Path.GetFullPath(rootPath);
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
_timeProvider = timeProvider;
|
||||
}
|
||||
|
||||
public void AddModuleLoad(string absoluteModulePath, string reason, IEnumerable<string> permissions, string? origin = null, DateTimeOffset? timestamp = null)
|
||||
|
||||
@@ -13,6 +13,12 @@ internal static class DenoRuntimeTraceRunner
|
||||
private const string EntrypointEnvVar = "STELLA_DENO_ENTRYPOINT";
|
||||
private const string BinaryEnvVar = "STELLA_DENO_BINARY";
|
||||
private const string RuntimeFileName = "deno-runtime.ndjson";
|
||||
private static readonly HashSet<string> AllowedBinaryNames = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"deno",
|
||||
"deno.exe",
|
||||
"deno.cmd"
|
||||
};
|
||||
|
||||
public static async Task<bool> TryExecuteAsync(
|
||||
LanguageAnalyzerContext context,
|
||||
@@ -28,29 +34,28 @@ internal static class DenoRuntimeTraceRunner
|
||||
return false;
|
||||
}
|
||||
|
||||
var entrypointPath = Path.GetFullPath(Path.Combine(context.RootPath, entrypoint));
|
||||
if (!File.Exists(entrypointPath))
|
||||
var rootPath = Path.GetFullPath(context.RootPath);
|
||||
if (!TryResolveEntrypointPath(rootPath, entrypoint, logger, out var entrypointPath))
|
||||
{
|
||||
logger?.LogWarning("Deno runtime trace skipped: entrypoint '{Entrypoint}' missing", entrypointPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
var shimPath = Path.Combine(context.RootPath, DenoRuntimeShim.FileName);
|
||||
if (!File.Exists(shimPath))
|
||||
{
|
||||
await DenoRuntimeShim.WriteAsync(context.RootPath, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var binary = Environment.GetEnvironmentVariable(BinaryEnvVar);
|
||||
var binary = ResolveBinary(rootPath, Environment.GetEnvironmentVariable(BinaryEnvVar), logger);
|
||||
if (string.IsNullOrWhiteSpace(binary))
|
||||
{
|
||||
binary = "deno";
|
||||
return false;
|
||||
}
|
||||
|
||||
var shimPath = Path.Combine(rootPath, DenoRuntimeShim.FileName);
|
||||
if (!File.Exists(shimPath))
|
||||
{
|
||||
await DenoRuntimeShim.WriteAsync(rootPath, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = binary,
|
||||
WorkingDirectory = context.RootPath,
|
||||
WorkingDirectory = rootPath,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
@@ -58,7 +63,7 @@ internal static class DenoRuntimeTraceRunner
|
||||
|
||||
startInfo.ArgumentList.Add("run");
|
||||
startInfo.ArgumentList.Add("--cached-only");
|
||||
startInfo.ArgumentList.Add("--allow-read");
|
||||
startInfo.ArgumentList.Add(BuildAllowReadArgument(rootPath, logger));
|
||||
startInfo.ArgumentList.Add("--allow-env");
|
||||
startInfo.ArgumentList.Add("--quiet");
|
||||
startInfo.ArgumentList.Add(shimPath);
|
||||
@@ -96,7 +101,7 @@ internal static class DenoRuntimeTraceRunner
|
||||
return false;
|
||||
}
|
||||
|
||||
var runtimePath = Path.Combine(context.RootPath, RuntimeFileName);
|
||||
var runtimePath = Path.Combine(rootPath, RuntimeFileName);
|
||||
if (!File.Exists(runtimePath))
|
||||
{
|
||||
logger?.LogWarning(
|
||||
@@ -108,6 +113,122 @@ internal static class DenoRuntimeTraceRunner
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryResolveEntrypointPath(
|
||||
string rootPath,
|
||||
string entrypoint,
|
||||
ILogger? logger,
|
||||
out string entrypointPath)
|
||||
{
|
||||
entrypointPath = string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(entrypoint))
|
||||
{
|
||||
logger?.LogWarning("Deno runtime trace skipped: entrypoint was empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var candidate = Path.GetFullPath(Path.Combine(rootPath, entrypoint));
|
||||
if (!IsWithinRoot(rootPath, candidate))
|
||||
{
|
||||
logger?.LogWarning("Deno runtime trace skipped: entrypoint '{Entrypoint}' not under root", entrypoint);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!File.Exists(candidate))
|
||||
{
|
||||
logger?.LogWarning("Deno runtime trace skipped: entrypoint '{Entrypoint}' missing", candidate);
|
||||
return false;
|
||||
}
|
||||
|
||||
entrypointPath = candidate;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) when (ex is ArgumentException or IOException or NotSupportedException or PathTooLongException or UnauthorizedAccessException)
|
||||
{
|
||||
logger?.LogWarning(ex, "Deno runtime trace skipped: entrypoint '{Entrypoint}' invalid", entrypoint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? ResolveBinary(string rootPath, string? binary, ILogger? logger)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(binary))
|
||||
{
|
||||
return "deno";
|
||||
}
|
||||
|
||||
var trimmed = binary.Trim();
|
||||
var fileName = Path.GetFileName(trimmed);
|
||||
if (string.IsNullOrWhiteSpace(fileName) || !AllowedBinaryNames.Contains(fileName))
|
||||
{
|
||||
logger?.LogWarning("Deno runtime trace skipped: binary '{Binary}' not allowlisted", trimmed);
|
||||
return null;
|
||||
}
|
||||
|
||||
var isPath = trimmed.Contains(Path.DirectorySeparatorChar) ||
|
||||
trimmed.Contains(Path.AltDirectorySeparatorChar) ||
|
||||
Path.IsPathRooted(trimmed);
|
||||
if (!isPath)
|
||||
{
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var candidate = Path.GetFullPath(Path.IsPathRooted(trimmed)
|
||||
? trimmed
|
||||
: Path.Combine(rootPath, trimmed));
|
||||
if (!IsWithinRoot(rootPath, candidate))
|
||||
{
|
||||
logger?.LogWarning("Deno runtime trace skipped: binary '{Binary}' not under root", trimmed);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!File.Exists(candidate))
|
||||
{
|
||||
logger?.LogWarning("Deno runtime trace skipped: binary '{Binary}' missing", candidate);
|
||||
return null;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
catch (Exception ex) when (ex is ArgumentException or IOException or NotSupportedException or PathTooLongException or UnauthorizedAccessException)
|
||||
{
|
||||
logger?.LogWarning(ex, "Deno runtime trace skipped: binary '{Binary}' invalid", trimmed);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildAllowReadArgument(string rootPath, ILogger? logger)
|
||||
{
|
||||
var comparison = OperatingSystem.IsWindows() ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
|
||||
var allowed = new HashSet<string>(comparison) { rootPath };
|
||||
var denoDir = Environment.GetEnvironmentVariable("DENO_DIR");
|
||||
if (!string.IsNullOrWhiteSpace(denoDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
var denoDirPath = Path.GetFullPath(denoDir, rootPath);
|
||||
allowed.Add(denoDirPath);
|
||||
}
|
||||
catch (Exception ex) when (ex is ArgumentException or IOException or NotSupportedException or PathTooLongException or UnauthorizedAccessException)
|
||||
{
|
||||
logger?.LogWarning(ex, "Deno runtime trace: invalid DENO_DIR '{DenoDir}'", denoDir);
|
||||
}
|
||||
}
|
||||
|
||||
var ordered = allowed.OrderBy(path => path, comparison);
|
||||
return $"--allow-read={string.Join(",", ordered)}";
|
||||
}
|
||||
|
||||
private static bool IsWithinRoot(string rootPath, string candidatePath)
|
||||
{
|
||||
var comparison = OperatingSystem.IsWindows() ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
|
||||
var normalizedRoot = rootPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||
return candidatePath.StartsWith(normalizedRoot, comparison);
|
||||
}
|
||||
|
||||
private static string Truncate(string? value, int maxLength = 400)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Deno.Internal.Runtime;
|
||||
@@ -8,7 +9,7 @@ internal static class DenoRuntimeTraceSerializer
|
||||
{
|
||||
private static readonly JsonWriterOptions WriterOptions = new()
|
||||
{
|
||||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
Encoder = JavaScriptEncoder.Default,
|
||||
Indented = false
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user