up
Some checks failed
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Some checks failed
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
@@ -125,6 +126,137 @@ public sealed class PythonLanguageAnalyzerTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EditableRequirementsUseExplicitKeyWithoutHostPathLeakAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
|
||||
try
|
||||
{
|
||||
var editableDir = Path.Combine(fixturePath, "editable-src");
|
||||
Directory.CreateDirectory(editableDir);
|
||||
|
||||
var requirementsPath = Path.Combine(fixturePath, "requirements.txt");
|
||||
await File.WriteAllTextAsync(requirementsPath, $"--editable {editableDir}{Environment.NewLine}", cancellationToken);
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
foreach (var component in root.EnumerateArray())
|
||||
{
|
||||
if (component.TryGetProperty("purl", out var purlElement) && purlElement.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
Assert.DoesNotContain("@editable", purlElement.GetString(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
var editableComponent = root.EnumerateArray().Single(static component =>
|
||||
component.TryGetProperty("name", out var nameElement)
|
||||
&& string.Equals("editable-src", nameElement.GetString(), StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
Assert.True(!editableComponent.TryGetProperty("purl", out var purlValue) || purlValue.ValueKind == JsonValueKind.Null);
|
||||
|
||||
var componentKey = editableComponent.GetProperty("componentKey").GetString();
|
||||
Assert.StartsWith("explicit::python::pypi::editable-src::sha256:", componentKey, StringComparison.Ordinal);
|
||||
|
||||
var metadata = editableComponent.GetProperty("metadata");
|
||||
Assert.Equal("true", metadata.GetProperty("declaredOnly").GetString());
|
||||
Assert.Equal("editable", metadata.GetProperty("declared.sourceType").GetString());
|
||||
Assert.Equal("requirements.txt", metadata.GetProperty("declared.source").GetString());
|
||||
Assert.Equal("requirements.txt", metadata.GetProperty("declared.locator").GetString());
|
||||
|
||||
var editableSpec = metadata.GetProperty("lockEditablePath").GetString();
|
||||
Assert.Equal("editable-src", editableSpec);
|
||||
Assert.DoesNotContain(fixturePath, editableSpec, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.DoesNotContain(":", editableSpec, StringComparison.Ordinal);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WheelArchiveDistInfo_IsVerifiedFromRecordAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
var distDir = Path.Combine(fixturePath, "dist");
|
||||
Directory.CreateDirectory(distDir);
|
||||
|
||||
var wheelPath = Path.Combine(distDir, "archivepkg-1.0.0-py3-none-any.whl");
|
||||
|
||||
var initBytes = Encoding.UTF8.GetBytes("__version__ = \"1.0.0\"\n");
|
||||
var metadataBytes = Encoding.UTF8.GetBytes(
|
||||
$"Metadata-Version: 2.1\nName: archivepkg\nVersion: 1.0.0\n{Environment.NewLine}");
|
||||
var wheelBytes = Encoding.UTF8.GetBytes(
|
||||
"Wheel-Version: 1.0\nGenerator: test\nRoot-Is-Purelib: true\nTag: py3-none-any\n");
|
||||
|
||||
var recordContent = new StringBuilder()
|
||||
.AppendLine($"archivepkg/__init__.py,sha256={ComputeSha256Base64(initBytes)},{initBytes.Length}")
|
||||
.AppendLine($"archivepkg-1.0.0.dist-info/METADATA,sha256={ComputeSha256Base64(metadataBytes)},{metadataBytes.Length}")
|
||||
.AppendLine($"archivepkg-1.0.0.dist-info/WHEEL,sha256={ComputeSha256Base64(wheelBytes)},{wheelBytes.Length}")
|
||||
.AppendLine("archivepkg-1.0.0.dist-info/RECORD,,")
|
||||
.ToString();
|
||||
var recordBytes = Encoding.UTF8.GetBytes(recordContent);
|
||||
|
||||
using (var stream = File.Create(wheelPath))
|
||||
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: false))
|
||||
{
|
||||
WriteEntry(archive, "archivepkg/__init__.py", initBytes);
|
||||
WriteEntry(archive, "archivepkg-1.0.0.dist-info/METADATA", metadataBytes);
|
||||
WriteEntry(archive, "archivepkg-1.0.0.dist-info/WHEEL", wheelBytes);
|
||||
WriteEntry(archive, "archivepkg-1.0.0.dist-info/RECORD", recordBytes);
|
||||
}
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.totalEntries", "4"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.hashedEntries", "3"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.missingFiles", "0"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.hashMismatches", "0"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.ioErrors", "0"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
|
||||
static void WriteEntry(ZipArchive archive, string entryName, byte[] content)
|
||||
{
|
||||
var entry = archive.CreateEntry(entryName);
|
||||
using var entryStream = entry.Open();
|
||||
entryStream.Write(content, 0, content.Length);
|
||||
}
|
||||
|
||||
static string ComputeSha256Base64(byte[] content)
|
||||
=> Convert.ToBase64String(SHA256.HashData(content));
|
||||
}
|
||||
|
||||
private static async Task CreatePythonPackageAsync(string root, string name, string version, CancellationToken cancellationToken)
|
||||
{
|
||||
var sitePackages = Path.Combine(root, "lib", "python3.11", "site-packages");
|
||||
|
||||
Reference in New Issue
Block a user