mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-05 07:54:38 +00:00
fix(relay): protect sessions against replayed commands (#7610)
Protect relay sessions against replayed commands with authenticated Noise NK negotiation, ordered records, and identity-bound security pins. Preserve legacy admission during migration and add daemon enforcement policy. All 21 CI checks passed. General engineering review is complete; specialist cryptographic review of the handwritten Noise implementation and static-key reuse remains required before release or deployment. Closes #359
This commit is contained in:
@@ -14,7 +14,7 @@ import { join } from "path";
|
||||
import { win32 } from "node:path";
|
||||
import { tmpdir } from "os";
|
||||
import pino from "pino";
|
||||
import { base64EncryptedWireByteLength } from "@getpaseo/relay";
|
||||
import { base64EncryptedWireByteLength, maxSecuredPlaintextByteLength } from "@getpaseo/relay";
|
||||
import {
|
||||
__resetCheckoutShortstatCacheForTests,
|
||||
__resetPullRequestStatusCacheForTests,
|
||||
@@ -1654,9 +1654,14 @@ const x = 1;
|
||||
CHECKOUT_DIFF_MAX_STRUCTURED_BYTES + frameEnvelopeHeadroomBytes,
|
||||
);
|
||||
|
||||
expect(CHECKOUT_DIFF_MAX_STRUCTURED_BYTES).toBe(24_117_208);
|
||||
// The cap is sized for the tighter of the legacy and protected relay framings.
|
||||
expect(CHECKOUT_DIFF_MAX_STRUCTURED_BYTES).toBe(
|
||||
maxSecuredPlaintextByteLength(relayFrameBytes) - frameEnvelopeHeadroomBytes,
|
||||
);
|
||||
expect(CHECKOUT_DIFF_MAX_STRUCTURED_BYTES).toBeLessThanOrEqual(24_117_208);
|
||||
expect(CHECKOUT_DIFF_MAX_STRUCTURED_BYTES).toBeGreaterThan(24_000_000);
|
||||
expect(diffWireBytes).toBeLessThan(relayFrameBytes);
|
||||
expect(maximumFrameWireBytes).toBe(relayFrameBytes);
|
||||
expect(maximumFrameWireBytes).toBeLessThanOrEqual(relayFrameBytes);
|
||||
});
|
||||
|
||||
it("marks tracked generated one-line diffs as too_large by content size", async () => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { setImmediate } from "node:timers/promises";
|
||||
import { TTLCache } from "@isaacs/ttlcache";
|
||||
import type { CheckoutCommit, CheckoutCommitFile } from "@getpaseo/protocol/messages";
|
||||
import { parseGitHubRemoteIdentity, parseGitRemoteLocation } from "@getpaseo/protocol/git-remote";
|
||||
import { maxBase64EncryptedPlaintextByteLength } from "@getpaseo/relay";
|
||||
import { maxSecuredPlaintextByteLength } from "@getpaseo/relay";
|
||||
import type { Logger } from "pino";
|
||||
import type { ParsedDiffFile } from "../server/utils/diff-highlighter.js";
|
||||
import {
|
||||
@@ -2162,7 +2162,7 @@ const CHECKOUT_DIFF_FRAME_HEADROOM_BYTES = 1024 * 1024;
|
||||
// binding: string frames are encrypted and base64-encoded. Reserve 1 MiB plaintext for
|
||||
// the surrounding WebSocket JSON envelope after inverting that exact wire expansion.
|
||||
export const CHECKOUT_DIFF_MAX_STRUCTURED_BYTES =
|
||||
maxBase64EncryptedPlaintextByteLength(MAX_RELAY_WEBSOCKET_MESSAGE_BYTES) -
|
||||
maxSecuredPlaintextByteLength(MAX_RELAY_WEBSOCKET_MESSAGE_BYTES) -
|
||||
CHECKOUT_DIFF_FRAME_HEADROOM_BYTES;
|
||||
|
||||
interface StructuredDiffAccumulator {
|
||||
|
||||
Reference in New Issue
Block a user