level is not optional

This commit is contained in:
Alistair Smith
2025-07-30 14:13:25 -07:00
parent 15543cafc8
commit aaa271d041
2 changed files with 39 additions and 24 deletions

View File

@@ -1243,20 +1243,22 @@ fn performSecurityScanAfterResolution(
Global.exit(1);
};
// Level is optional, defaults to "warn"
var level = SecurityAdvisoryLevel.warn;
if (item_obj.get("level")) |level_expr| {
if (level_expr.asString(manager.allocator)) |level_str| {
if (std.mem.eql(u8, level_str, "fatal")) {
level = .fatal;
} else if (std.mem.eql(u8, level_str, "warn")) {
level = .warn;
} else {
Output.errGeneric("Security advisory at index {d} 'level' field must be 'fatal' or 'warn', got: '{s}'", .{ i, level_str });
Global.exit(1);
}
}
}
const level_expr = item_obj.get("level") orelse {
Output.errGeneric("Security advisory at index {d} missing required 'level' field", .{i});
Global.exit(1);
};
const level_str = level_expr.asString(manager.allocator) orelse {
Output.errGeneric("Security advisory at index {d} 'level' field must be a string", .{i});
Global.exit(1);
};
const level = if (std.mem.eql(u8, level_str, "fatal"))
SecurityAdvisoryLevel.fatal
else if (std.mem.eql(u8, level_str, "warn"))
SecurityAdvisoryLevel.warn
else {
Output.errGeneric("Security advisory at index {d} 'level' field must be 'fatal' or 'warn', got: '{s}'", .{ i, level_str });
Global.exit(1);
};
const advisory = SecurityAdvisory{
.level = level,

View File

@@ -334,6 +334,20 @@ describe("Invalid Advisory Formats", () => {
},
});
run("advisory missing level field", {
scanner: async () => [
{
package: "bar",
description: "Missing level",
url: "https://example.com",
} as any,
],
expectedExitCode: 1,
expect: ({ err }) => {
expect(err).toContain("Security advisory at index 0 missing required 'level' field");
},
});
run("advisory url field not string", {
scanner: async () => [
{
@@ -375,7 +389,7 @@ describe("Invalid Advisory Formats", () => {
],
expectedExitCode: 1,
expect: ({ err }) => {
expect(err).toContain("Security advisory at index 0 'level' field must be 'fatal' or 'warn'");
expect(err).toContain("Security advisory at index 0 'level' field must be a string");
},
});
@@ -573,7 +587,7 @@ describe("Edge Cases", () => {
},
});
run("advisory without optional level field defaults to warn", {
run("advisory without level field", {
scanner: async ({ packages }) => [
{
package: packages[0].name,
@@ -581,14 +595,13 @@ describe("Edge Cases", () => {
url: "https://example.com",
} as any,
],
expectedExitCode: 0,
expect: ({ out }) => {
expect(out).toContain("WARN: bar");
expect(out).toContain("No level specified");
expectedExitCode: 1,
expect: ({ err }) => {
expect(err).toContain("Security advisory at index 0 missing required 'level' field");
},
});
run("null values in optional fields", {
run("null values in level field", {
scanner: async ({ packages }) => [
{
package: packages[0].name,
@@ -597,9 +610,9 @@ describe("Edge Cases", () => {
url: "https://example.com",
},
],
expectedExitCode: 0, // null level should default to warn
expect: ({ out }) => {
expect(out).toContain("WARN: bar");
expectedExitCode: 1,
expect: ({ err }) => {
expect(err).toContain("Security advisory at index 0 'level' field must be a string");
},
});
});