ribaunt 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -6
- package/SECURITY.md +36 -0
- package/dist/cjs/index.d.ts +43 -24
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +250 -247
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/redis.d.ts +13 -0
- package/dist/cjs/redis.d.ts.map +1 -0
- package/dist/cjs/redis.js +53 -0
- package/dist/cjs/redis.js.map +1 -0
- package/dist/index.d.ts +43 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +249 -247
- package/dist/index.js.map +1 -1
- package/dist/redis.d.ts +13 -0
- package/dist/redis.d.ts.map +1 -0
- package/dist/redis.js +49 -0
- package/dist/redis.js.map +1 -0
- package/dist/solver-worker.d.ts +2 -0
- package/dist/solver-worker.d.ts.map +1 -0
- package/dist/solver-worker.js +15 -0
- package/dist/solver-worker.js.map +1 -0
- package/dist/solver.d.ts +10 -0
- package/dist/solver.d.ts.map +1 -1
- package/dist/solver.js +14 -0
- package/dist/solver.js.map +1 -1
- package/dist/widget-react.d.ts +8 -11
- package/dist/widget-react.d.ts.map +1 -1
- package/dist/widget-react.js +30 -5
- package/dist/widget-react.js.map +1 -1
- package/dist/widget.d.ts +30 -1
- package/dist/widget.d.ts.map +1 -1
- package/dist/widget.js +132 -19
- package/dist/widget.js.map +1 -1
- package/dist/worker-client.d.ts +8 -0
- package/dist/worker-client.d.ts.map +1 -0
- package/dist/worker-client.js +78 -0
- package/dist/worker-client.js.map +1 -0
- package/package.json +23 -2
- package/dist/cjs/solver.d.ts +0 -16
- package/dist/cjs/solver.d.ts.map +0 -1
- package/dist/cjs/solver.js +0 -89
- package/dist/cjs/solver.js.map +0 -1
- package/dist/cjs/widget-browser.d.ts +0 -7
- package/dist/cjs/widget-browser.d.ts.map +0 -1
- package/dist/cjs/widget-browser.js +0 -12
- package/dist/cjs/widget-browser.js.map +0 -1
- package/dist/cjs/widget-react.d.ts +0 -40
- package/dist/cjs/widget-react.d.ts.map +0 -1
- package/dist/cjs/widget-react.js +0 -182
- package/dist/cjs/widget-react.js.map +0 -1
- package/dist/cjs/widget.d.ts +0 -97
- package/dist/cjs/widget.d.ts.map +0 -1
- package/dist/cjs/widget.js +0 -519
- package/dist/cjs/widget.js.map +0 -1
package/README.md
CHANGED
|
@@ -37,11 +37,14 @@ pnpm add ribaunt
|
|
|
37
37
|
## Quick Start
|
|
38
38
|
|
|
39
39
|
Set a strong secret in your server environment. Keep this server-only.
|
|
40
|
+
Ribaunt requires at least 32 UTF-8 bytes; generate a random value rather than a memorable password.
|
|
40
41
|
|
|
41
42
|
```env
|
|
42
43
|
RIBAUNT_SECRET="replace-with-a-long-random-secret"
|
|
43
44
|
```
|
|
44
45
|
|
|
46
|
+
> **Upgrading from v0.1:** `verifySolution()` now returns a structured result object, not a boolean. Always check `result.valid`; using the result object directly in an `if` condition is unsafe because JavaScript objects are truthy.
|
|
47
|
+
|
|
45
48
|
Create two endpoints: one to issue challenges and one to verify solutions.
|
|
46
49
|
|
|
47
50
|
```ts
|
|
@@ -60,10 +63,10 @@ app.get('/api/captcha/challenge', (_req, res) => {
|
|
|
60
63
|
|
|
61
64
|
app.post('/api/captcha/verify', async (req, res) => {
|
|
62
65
|
const { tokens, solutions } = req.body;
|
|
63
|
-
const
|
|
66
|
+
const result = await verifySolution(tokens, solutions);
|
|
64
67
|
|
|
65
|
-
if (!valid) {
|
|
66
|
-
return res.status(400).json({ success: false, error:
|
|
68
|
+
if (!result.valid) {
|
|
69
|
+
return res.status(400).json({ success: false, error: result.reason });
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
return res.json({ success: true });
|
|
@@ -142,10 +145,11 @@ Validate user- or config-controlled values before passing them to `createChallen
|
|
|
142
145
|
|
|
143
146
|
### `verifySolution(tokens, solutions, options?)`
|
|
144
147
|
|
|
145
|
-
Verifies submitted solutions and returns
|
|
148
|
+
Verifies submitted solutions and returns a structured result:
|
|
149
|
+
`{ valid: true }` or `{ valid: false, reason, message }`.
|
|
146
150
|
|
|
147
151
|
```ts
|
|
148
|
-
const
|
|
152
|
+
const result = await verifySolution(tokens, solutions, {
|
|
149
153
|
onWarning: (warning) => {
|
|
150
154
|
console.log('captcha warning', warning.reason, warning.message);
|
|
151
155
|
},
|
|
@@ -155,7 +159,7 @@ const valid = await verifySolution(tokens, solutions, {
|
|
|
155
159
|
Replay prevention defaults to `local`, which blocks token reuse in the current process. For serverless or horizontally scaled deployments, use `replayPrevention: 'remote'` with an atomic distributed store.
|
|
156
160
|
|
|
157
161
|
```ts
|
|
158
|
-
const
|
|
162
|
+
const result = await verifySolution(tokens, solutions, {
|
|
159
163
|
replayPrevention: 'remote',
|
|
160
164
|
replayStore: {
|
|
161
165
|
consume: async (jti, expiresAt) => {
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
Ribaunt is a proof-of-work CAPTCHA library, so security reports are especially
|
|
4
|
+
important when they affect challenge signing, verification bypasses, replay
|
|
5
|
+
prevention, widget behavior, or server-only secret handling.
|
|
6
|
+
|
|
7
|
+
## Supported Versions
|
|
8
|
+
|
|
9
|
+
| Version | Security support |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Latest npm release | Supported |
|
|
12
|
+
| Older releases | Best effort |
|
|
13
|
+
|
|
14
|
+
## Reporting a Vulnerability
|
|
15
|
+
|
|
16
|
+
Please do not open a public GitHub issue for suspected vulnerabilities.
|
|
17
|
+
|
|
18
|
+
Report vulnerabilities privately through GitHub Security Advisories:
|
|
19
|
+
|
|
20
|
+
https://github.com/ribaunt/ribaunt/security/advisories/new
|
|
21
|
+
|
|
22
|
+
Include as much of the following as you can:
|
|
23
|
+
|
|
24
|
+
- Affected Ribaunt version or commit
|
|
25
|
+
- Reproduction steps
|
|
26
|
+
- Expected and observed behavior
|
|
27
|
+
- Security impact
|
|
28
|
+
- Runtime and browser environment, if relevant
|
|
29
|
+
- Proof of concept, logs, or screenshots
|
|
30
|
+
|
|
31
|
+
## What to Expect
|
|
32
|
+
|
|
33
|
+
After receiving a report, maintainers will acknowledge it, investigate the
|
|
34
|
+
issue, and coordinate a fix when appropriate. If the issue is confirmed, the fix
|
|
35
|
+
will be released and a security advisory will be published when disclosure is
|
|
36
|
+
safe.
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -3,22 +3,59 @@ export interface ChallengeSolution {
|
|
|
3
3
|
nonce: string;
|
|
4
4
|
hash: string;
|
|
5
5
|
}
|
|
6
|
+
export interface ClientCalibration {
|
|
7
|
+
iterations: number;
|
|
8
|
+
durationMs: number;
|
|
9
|
+
}
|
|
10
|
+
export interface WorkloadBounds {
|
|
11
|
+
minDifficulty?: number;
|
|
12
|
+
maxDifficulty?: number;
|
|
13
|
+
minAmount?: number;
|
|
14
|
+
maxAmount?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface AdaptiveWorkloadOptions extends WorkloadBounds {
|
|
17
|
+
riskScore?: number;
|
|
18
|
+
targetDurationMs?: number;
|
|
19
|
+
calibration?: ClientCalibration;
|
|
20
|
+
}
|
|
21
|
+
export interface Workload {
|
|
22
|
+
difficulty: number;
|
|
23
|
+
amount: number;
|
|
24
|
+
estimatedAttempts: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ChallengeOptions {
|
|
27
|
+
difficulty?: number;
|
|
28
|
+
amount?: number;
|
|
29
|
+
ttlSeconds?: number;
|
|
30
|
+
context?: string;
|
|
31
|
+
workload?: Pick<Workload, 'difficulty' | 'amount'>;
|
|
32
|
+
}
|
|
6
33
|
export interface ReplayStore {
|
|
7
34
|
consume(jti: string, expiresAt: number): Promise<boolean>;
|
|
35
|
+
consumeMany?(jtis: string[], expiresAt: number): Promise<boolean>;
|
|
8
36
|
}
|
|
9
37
|
export type ReplayPreventionMode = 'disabled' | 'local' | 'remote';
|
|
10
38
|
export interface VerifySolutionOptions {
|
|
11
39
|
replayPrevention?: ReplayPreventionMode;
|
|
12
40
|
replayStore?: ReplayStore;
|
|
41
|
+
context?: string;
|
|
13
42
|
debug?: boolean;
|
|
14
43
|
onWarning?: (warning: VerifyWarning) => void;
|
|
15
44
|
}
|
|
16
|
-
export type
|
|
45
|
+
export type VerifyFailureReason = 'invalid-token' | 'expired-token' | 'invalid-solution' | 'context-mismatch' | 'replay-detected' | 'configuration-error';
|
|
46
|
+
export type VerifyWarningReason = VerifyFailureReason;
|
|
17
47
|
export interface VerifyWarning {
|
|
18
48
|
reason: VerifyWarningReason;
|
|
19
49
|
message: string;
|
|
20
50
|
error?: unknown;
|
|
21
51
|
}
|
|
52
|
+
export type VerifySolutionResult = {
|
|
53
|
+
valid: true;
|
|
54
|
+
} | {
|
|
55
|
+
valid: false;
|
|
56
|
+
reason: VerifyFailureReason;
|
|
57
|
+
message: string;
|
|
58
|
+
};
|
|
22
59
|
export interface SolveChallengeOptions {
|
|
23
60
|
maxIterations?: number;
|
|
24
61
|
maxDurationMs?: number;
|
|
@@ -26,34 +63,16 @@ export interface SolveChallengeOptions {
|
|
|
26
63
|
export declare class LocalReplayStore implements ReplayStore {
|
|
27
64
|
private usedTokens;
|
|
28
65
|
consume(jti: string, expiresAt: number): Promise<boolean>;
|
|
66
|
+
consumeMany(jtis: string[], expiresAt: number): Promise<boolean>;
|
|
29
67
|
private cleanup;
|
|
30
68
|
}
|
|
31
69
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* @param difficulty - Number of leading zeros required in the hash (default 5)
|
|
35
|
-
* @param amount - Number of challenges to create (default 4)
|
|
36
|
-
* @param ttlSeconds - Time to live for each challenge in seconds (default 30)
|
|
37
|
-
* @returns An array of JWT challenge tokens
|
|
70
|
+
* Selects bounded proof-of-work using a server-owned risk floor and untrusted timing calibration.
|
|
38
71
|
*/
|
|
72
|
+
export declare function selectWorkload(options?: AdaptiveWorkloadOptions): Workload;
|
|
39
73
|
export declare function createChallenge(difficulty?: number, amount?: number, ttlSeconds?: number): ChallengeToken[];
|
|
40
|
-
|
|
41
|
-
* Solves one or more PoW challenges encoded in JWT tokens.
|
|
42
|
-
*
|
|
43
|
-
* @param token - The JWT challenge token or an array of tokens
|
|
44
|
-
* @param options - Optional guardrails for test/debug usage (`maxIterations`, `maxDurationMs`)
|
|
45
|
-
* @returns The nonce/hash pair for single input or an array of them for multiple tokens
|
|
46
|
-
*/
|
|
47
|
-
export declare function solveChallenge(token: ChallengeToken): ChallengeSolution | undefined;
|
|
74
|
+
export declare function createChallenge(options: ChallengeOptions): ChallengeToken[];
|
|
48
75
|
export declare function solveChallenge(token: ChallengeToken, options?: SolveChallengeOptions): ChallengeSolution | undefined;
|
|
49
|
-
export declare function solveChallenge(token: ChallengeToken[]): ChallengeSolution[] | undefined;
|
|
50
76
|
export declare function solveChallenge(token: ChallengeToken[], options?: SolveChallengeOptions): ChallengeSolution[] | undefined;
|
|
51
|
-
|
|
52
|
-
* Verifies a PoW solution returned by the client.
|
|
53
|
-
*
|
|
54
|
-
* @param token - The original JWT issued as the challenge (single token or array of tokens)
|
|
55
|
-
* @param nonce - The nonce/answer submitted by the client (single nonce, array of nonces, or array of solution objects)
|
|
56
|
-
* @returns true only if every provided solution is valid; otherwise false
|
|
57
|
-
*/
|
|
58
|
-
export declare function verifySolution(token: ChallengeToken | ChallengeToken[], nonce: number | string | Array<number | string> | ChallengeSolution | ChallengeSolution[], options?: VerifySolutionOptions): Promise<boolean>;
|
|
77
|
+
export declare function verifySolution(token: ChallengeToken | ChallengeToken[], nonce: number | string | Array<number | string> | ChallengeSolution | ChallengeSolution[], options?: VerifySolutionOptions): Promise<VerifySolutionResult>;
|
|
59
78
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|