-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix(core): improve error messages for provenance checks #32680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
View your CI Pipeline Execution ↗ for commit 46a2a4a
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nx Cloud is proposing a fix for your failed CI:
We've fixed the formatting issue in the provenance.ts file by removing trailing whitespace on line 70. This ensures the file passes the format:check validation and maintains consistent code formatting across the codebase.
We verified this fix by re-running nx-cloud record -- nx format:check
.
diff --git a/packages/nx/src/utils/provenance.ts b/packages/nx/src/utils/provenance.ts
index abb2a6219b..988cab9c7e 100644
--- a/packages/nx/src/utils/provenance.ts
+++ b/packages/nx/src/utils/provenance.ts
@@ -67,7 +67,7 @@ export async function ensurePackageHasProvenance(
if (!jsonResponse || typeof jsonResponse !== 'object') {
throw new Error('Invalid attestation response format');
}
-
+
attestations = jsonResponse as { attestations: Attestation[] };
} catch (error) {
throw noProvenanceError(
⚙️ An Nx Cloud workspace admin can disable these reviews in workspace settings.
3cb2158
to
ec2fbe6
Compare
ec2fbe6
to
946c3c5
Compare
const provenanceAttestation = attestations?.attestations?.find( | ||
(a) => a.predicateType === 'https://slsa.dev/provenance/v1' | ||
); | ||
} | ||
if (workflowParameters?.path !== '.github/workflows/publish.yml') { | ||
throw noProvenanceError( | ||
packageName, | ||
packageVersion, | ||
'Publishing workflow does not match .github/workflows/publish.yml' | ||
|
||
const dsseEnvelopePayload = JSON.parse( | ||
Buffer.from( | ||
provenanceAttestation.bundle.dsseEnvelope.payload, | ||
'base64' | ||
).toString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There appears to be a potential null reference issue in this code. After finding the provenance attestation, the code immediately tries to access provenanceAttestation.bundle.dsseEnvelope.payload
without first verifying that provenanceAttestation
exists.
Consider adding a null check after line 60:
if (!provenanceAttestation) {
throw new ProvenanceError(
packageName,
packageVersion,
'No provenance attestation found'
);
}
This would prevent a runtime error if no matching attestation is found and provide a more descriptive error message.
const provenanceAttestation = attestations?.attestations?.find( | |
(a) => a.predicateType === 'https://slsa.dev/provenance/v1' | |
); | |
} | |
if (workflowParameters?.path !== '.github/workflows/publish.yml') { | |
throw noProvenanceError( | |
packageName, | |
packageVersion, | |
'Publishing workflow does not match .github/workflows/publish.yml' | |
const dsseEnvelopePayload = JSON.parse( | |
Buffer.from( | |
provenanceAttestation.bundle.dsseEnvelope.payload, | |
'base64' | |
).toString() | |
const provenanceAttestation = attestations?.attestations?.find( | |
(a) => a.predicateType === 'https://slsa.dev/provenance/v1' | |
); | |
if (!provenanceAttestation) { | |
throw new ProvenanceError( | |
packageName, | |
packageVersion, | |
'No provenance attestation found' | |
); | |
} | |
const dsseEnvelopePayload = JSON.parse( | |
Buffer.from( | |
provenanceAttestation.bundle.dsseEnvelope.payload, | |
'base64' | |
).toString() |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
} | ||
|
||
const { stdout } = await execAsync(`${pm} view ${pkg}@${version} ${args}`, { | ||
const { stdout } = await execAsync(`${pm} ${pkg}@${version} ${args}`, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical bug: The 'view' command has been removed from the npm command, making it invalid. The line should be ${pm} view ${pkg}@${version} ${args}
not ${pm} ${pkg}@${version} ${args}
. This will cause npm commands to fail with 'command not found' errors.
const { stdout } = await execAsync(`${pm} ${pkg}@${version} ${args}`, { | |
const { stdout } = await execAsync(`${pm} view ${pkg}@${version} ${args}`, { |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MaxKless this seems legit?
const distSha = Buffer.from( | ||
npmViewResult.dist.integrity.replace('sha512-', ''), | ||
'base64' | ||
).toString('hex'); | ||
const attestationSha = dsseEnvelopePayload.subject[0].digest.sha512; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical null pointer bug: The code accesses npmViewResult.dist.integrity
and dsseEnvelopePayload.subject[0].digest.sha512
without null checks. If dist
, integrity
, subject
, or the first subject element is null/undefined, this will cause a TypeError. Add proper null checks before accessing these nested properties.
const distSha = Buffer.from( | |
npmViewResult.dist.integrity.replace('sha512-', ''), | |
'base64' | |
).toString('hex'); | |
const attestationSha = dsseEnvelopePayload.subject[0].digest.sha512; | |
const distSha = Buffer.from( | |
npmViewResult?.dist?.integrity?.replace('sha512-', '') ?? '', | |
'base64' | |
).toString('hex'); | |
const attestationSha = dsseEnvelopePayload?.subject?.[0]?.digest?.sha512; |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
throw new ProvenanceError( | ||
packageName, | ||
packageVersion, | ||
`Version ref does not match refs/tags/${npmViewResult.version}` | ||
error.message || error | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic error in error handling: The catch block uses error.message || error
which will always evaluate to error.message
when it exists, even if it's an empty string. This could result in empty error messages. Use error.message || String(error)
or error?.message ?? String(error)
to ensure a meaningful error message is always provided.
throw new ProvenanceError( | |
packageName, | |
packageVersion, | |
`Version ref does not match refs/tags/${npmViewResult.version}` | |
error.message || error | |
); | |
throw new ProvenanceError( | |
packageName, | |
packageVersion, | |
error.message || String(error) | |
); |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
(cherry picked from commit d02b7f4)
This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request. |
Current Behavior
there are instances where the provenance checks might error out with unclear errors, leading to confusion.
Expected Behavior
the whole provenance check always throws a proper provenance error if it fails and some more common cases are handled.