Skip to content

Commit 558eea5

Browse files
authored
feat: add rule RES.02
Signed-off-by: Mats Johansson <extern.mats.johansson@digg.se>
1 parent 1516404 commit 558eea5

File tree

7 files changed

+223
-14
lines changed

7 files changed

+223
-14
lines changed

GUIDELINES.md

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,45 +43,47 @@ Detta dokument specificerar reglerna som verktyget tillämpar.
4343
2. [Område: Datum- och tidsformat](#område-datum--och-tidsformat)
4444
- [ID: DOT.01](#id-dot01)
4545
- [ID: DOT.04](#id-dot04)
46-
3. [Område: URL Format och namngivning](#område-url-format-och-namngivning)
46+
3. [Område: Resurser](#område-resurser)
47+
- [ID: RES.02](#id-res02)
48+
4. [Område: URL Format och namngivning](#område-url-format-och-namngivning)
4749
- [ID: UFN.01](#id-ufn01)
4850
- [ID: UFN.02](#id-ufn02)
4951
- [ID: UFN.05](#id-ufn05)
5052
- [ID: UFN.07](#id-ufn07)
5153
- [ID: UFN.08](#id-ufn08)
5254
- [ID: UFN.09](#id-ufn09)
53-
4. [Område: API Message](#område-api-message)
55+
5. [Område: API Message](#område-api-message)
5456
- [ID: AME.01](#id-ame01)
5557
- [ID: AME.02](#id-ame02)
5658
- [ID: AME.04](#id-ame04)
5759
- [ID: AME.05](#id-ame05)
5860
- [ID: AME.07](#id-ame07)
59-
5. [Område: API Request](#område-api-request)
61+
6. [Område: API Request](#område-api-request)
6062
- [ID: ARQ.01](#id-arq01)
6163
- [ID: ARQ.03](#id-arq03)
6264
- [ID: ARQ.05](#id-arq05)
63-
6. [Område: Felhantering](#område-felhantering)
65+
7. [Område: Felhantering](#område-felhantering)
6466
- [ID: FEL.01](#id-fel01)
6567
- [ID: FEL.02](#id-fel02)
66-
7. [Område: Versionhantering](#område-versionhantering)
68+
8. [Område: Versionhantering](#område-versionhantering)
6769
- [ID: VER.05](#id-ver05)
6870
- [ID: VER.06](#id-ver06)
69-
8. [Område: Filtrering, paginering och sökparametrar](#område-filtrering-paginering-och-sökparametrar)
71+
9. [Område: Filtrering, paginering och sökparametrar](#område-filtrering-paginering-och-sökparametrar)
7072
- [ID: FNS.01](#id-fns01)
7173
- [ID: FNS.03](#id-fns03)
7274
- [ID: FNS.05](#id-fns05)
7375
- [ID: FNS.06](#id-fns06)
7476
- [ID: FNS.07](#id-fns07)
7577
- [ID: FNS.08](#id-fns08)
7678
- [ID: FNS.09](#id-fns09)
77-
9. [Område: Säkerhet](#område-säkerhet)
78-
- [ID: SAK.01](#id-sak01)
79-
- [ID: SAK.09](#id-sak09)
80-
- [ID: SAK.10](#id-sak10)
81-
- [ID: SAK.15](#id-sak15)
82-
- [ID: SAK.16](#id-sak16)
83-
- [ID: SAK.18](#id-sak18)
84-
10. [Område: Förutsättningar](#område-förutsättningar)
79+
10. [Område: Säkerhet](#område-säkerhet)
80+
- [ID: SAK.01](#id-sak01)
81+
- [ID: SAK.09](#id-sak09)
82+
- [ID: SAK.10](#id-sak10)
83+
- [ID: SAK.15](#id-sak15)
84+
- [ID: SAK.16](#id-sak16)
85+
- [ID: SAK.18](#id-sak18)
86+
11. [Område: Förutsättningar](#område-förutsättningar)
8587
- [ID: FOR.02](#id-for02)
8688

8789
## Område: Dokumentation
@@ -425,6 +427,40 @@ I exemplet ovan, så exemplifieras regeln med att oavsett typ av operation, unde
425427

426428
---
427429

430+
## Område: Resurser
431+
432+
**Täckningsgrad: 17%**
433+
434+
### ID: RES.02
435+
436+
**Krav:** Primärnycklar eller personligt identifierbar information (personnummer, etc.) BÖR INTE exponeras.
437+
438+
**Typ:** BÖR
439+
440+
**JSON Path Plus-uttryck:**
441+
442+
```
443+
$.paths[*].*.parameters[*]
444+
```
445+
446+
**Förklaring:**
447+
Regeln kontrollerar att parametrar av typerna query och path inte använder följande namn:
448+
449+
- pnr
450+
- personalidentitynumber
451+
- personnummer
452+
- personnr
453+
- ssn
454+
- socialsecuritynumber
455+
456+
**Exempel:**
457+
458+
![Exempelbild på hur parametrar anges på ett korrekt sätt i en OpenAPI Description](images/res02.png)
459+
460+
_Exemplet ovan är giltigt då namnet på parametern inte är ett av ovanstående._
461+
462+
---
463+
428464
## Område: URL Format och namngivning
429465

430466
**Täckningsgrad: 54%**

REUSE.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ path = [
5151
"images/fns07.png",
5252
"images/fns08.png",
5353
"images/fns09.png",
54+
"images/res02.png",
5455
"images/rest-api-profil.png",
5556
"images/sak01.png",
5657
"images/sak09.png",

images/res02.png

15 KB
Loading

rulesets/ResRules.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// SPDX-FileCopyrightText: 2025 diggsweden/rest-api-profil-lint-processor
2+
//
3+
// SPDX-License-Identifier: EUPL-1.2
4+
5+
import { DiagnosticSeverity } from '@stoplight/types';
6+
import { CustomProperties } from '../ruleinterface/CustomProperties.ts';
7+
import { BaseRuleset } from './BaseRuleset.ts';
8+
import { personalIdentityNumberFieldNames } from './constants/ResConstants.ts';
9+
10+
const moduleName: string = 'ResRules.ts';
11+
12+
export class Res02 extends BaseRuleset {
13+
static customProperties: CustomProperties = {
14+
område: 'Resurser',
15+
id: 'RES.02',
16+
};
17+
message = 'Primärnycklar eller personligt identifierbar information (personnummer, etc.) BÖR INTE exponeras. ';
18+
given = '$.paths[*].*.parameters[*]';
19+
then = [
20+
{
21+
function: (targetVal: any, _opts: string, paths: string[]) => {
22+
if (targetVal.in == 'query' || targetVal.in == 'path') {
23+
const lowerCaseTargetVal = targetVal.name.toLowerCase();
24+
const containsPersonalIdentityNumber = personalIdentityNumberFieldNames.includes(lowerCaseTargetVal);
25+
if (containsPersonalIdentityNumber) {
26+
return [
27+
{
28+
message: this.message,
29+
severity: this.severity,
30+
paths: paths,
31+
},
32+
];
33+
}
34+
}
35+
return [];
36+
},
37+
},
38+
{
39+
function: (targetVal: string, _opts: string, paths: string[]) => {
40+
this.trackRuleExecutionHandler(
41+
JSON.stringify(targetVal, null, 2),
42+
_opts,
43+
paths,
44+
this.severity,
45+
this.constructor.name,
46+
moduleName,
47+
Res02.customProperties
48+
);
49+
},
50+
},
51+
];
52+
severity = DiagnosticSeverity.Warning;
53+
constructor() {
54+
super();
55+
super.initializeFormats(['OAS3']);
56+
}
57+
}
58+
59+
export default { Res02 };

rulesets/constants/ResConstants.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-FileCopyrightText: 2025 diggsweden/rest-api-profil-lint-processor
2+
//
3+
// SPDX-License-Identifier: EUPL-1.2
4+
5+
export const personalIdentityNumberFieldNames = [
6+
'pnr',
7+
'personalIdentityNumber',
8+
'personnummer',
9+
'personnr',
10+
'ssn',
11+
'socialSecurityNumber',
12+
];

tests/res.test.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// SPDX-FileCopyrightText: 2025 diggsweden/rest-api-profil-lint-processor
2+
//
3+
// SPDX-License-Identifier: EUPL-1.2
4+
5+
import { DiagnosticSeverity } from '@stoplight/types';
6+
import testRule from './util/helperTest.ts';
7+
8+
testRule('Res02', [
9+
{
10+
name: 'ogiltigt testfall - Personnummer BÖR INTE förekomma i en resurs (query param) ',
11+
document: {
12+
openapi: '3.1.0',
13+
info: { version: '1.0.0' },
14+
paths: {
15+
'/pets': {
16+
get: {
17+
parameters: [
18+
{
19+
name: 'pnr',
20+
in: 'query',
21+
},
22+
],
23+
},
24+
},
25+
},
26+
},
27+
errors: [
28+
{
29+
message: 'Primärnycklar eller personligt identifierbar information (personnummer, etc.) BÖR INTE exponeras.',
30+
severity: DiagnosticSeverity.Warning,
31+
},
32+
],
33+
},
34+
{
35+
name: 'giltigt testfall - Personnummer BÖR INTE förekomma i en resurs (query param) ',
36+
document: {
37+
openapi: '3.1.0',
38+
info: { version: '1.0.0' },
39+
paths: {
40+
'/pets': {
41+
get: {
42+
parameters: [
43+
{
44+
name: 'title',
45+
in: 'query',
46+
},
47+
],
48+
},
49+
},
50+
},
51+
},
52+
errors: [],
53+
},
54+
{
55+
name: 'ogiltigt testfall - Personnummer BÖR INTE förekomma i en resurs (path param) ',
56+
document: {
57+
openapi: '3.1.0',
58+
info: { version: '1.0.0' },
59+
paths: {
60+
'/pets': {
61+
get: {
62+
parameters: [
63+
{
64+
name: 'pnr',
65+
in: 'path',
66+
},
67+
],
68+
},
69+
},
70+
},
71+
},
72+
errors: [
73+
{
74+
message: 'Primärnycklar eller personligt identifierbar information (personnummer, etc.) BÖR INTE exponeras.',
75+
severity: DiagnosticSeverity.Warning,
76+
},
77+
],
78+
},
79+
{
80+
name: 'giltigt testfall - Personnummer BÖR INTE förekomma i en resurs (path param) ',
81+
document: {
82+
openapi: '3.1.0',
83+
info: { version: '1.0.0' },
84+
paths: {
85+
'/pets': {
86+
get: {
87+
parameters: [
88+
{
89+
name: 'title',
90+
in: 'path',
91+
},
92+
],
93+
},
94+
},
95+
},
96+
},
97+
errors: [],
98+
},
99+
]);

tests/util/rulesetTest.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import * as AmeRules from '../../rulesets/AmeRules.ts';
1616
import * as ForRules from '../../rulesets/ForRules.ts';
1717
import * as DotRules from '../../rulesets/DotRules.ts';
1818
import * as FelRules from '../../rulesets/FelRules.ts';
19+
import * as ResRules from '../../rulesets/ResRules.ts';
1920

2021
const ruleInstances: Record<string, any> = {};
2122

@@ -80,6 +81,7 @@ const ruleTypes = [
8081
DokRules.Dok03License,
8182
DokRules.Dok03LicenseName,
8283
DokRules.Dok03LicenseUrl,
84+
ResRules.Res02,
8385
];
8486
ruleTypes.forEach((RuleClass) => {
8587
const instance = new RuleClass();

0 commit comments

Comments
 (0)