Skip to content

Commit 9e2d461

Browse files
authored
Added security guidance (#236)
* Added security guidance * Mention sedgid and remove poor example
1 parent a48e626 commit 9e2d461

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ API Documentation
106106
Full API documentation is available [right here](https://apitools.dev/swagger-parser/docs/)
107107

108108

109+
Security
110+
--------------------------
111+
The library, by default, attempts to resolve any files referenced using `$ref`, without considering file extensions or the location of the files. This can result in Local File Inclusion (LFI), thus, potentially sensitive information disclosure. Developers must be cautious when working with documents from untrusted sources. See [here](SECURITY.md) for more details and information on how to mitigate LFI.
112+
109113

110114
Contributing
111115
--------------------------

SECURITY.md

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Security Considerations
2+
3+
## Avoiding Local File Inclusion
4+
5+
### Default Behaviour
6+
7+
The library, by default, attempts to resolve any files pointed to by `$ref`, which can be a problem in specific scenarios, for example:
8+
9+
* A backend service uses the library, AND
10+
* The service processes OpenAPI documents from untrusted sources, AND
11+
* The service performs actual requests based on the processed OpenAPI document
12+
13+
For example, the below OpenAPI document refers to `/etc/passwd` via the `leak` property of the Pet object.
14+
15+
```yaml
16+
openapi: 3.0.2
17+
info:
18+
title: Example Document based on PetStore
19+
version: 1.0.11
20+
servers:
21+
- url: /api/v3
22+
paths:
23+
/pet:
24+
put:
25+
summary: Update an existing pet
26+
description: CHECK THE PET OBJECT leak PROPERTY!
27+
operationId: updatePet
28+
requestBody:
29+
description: Update an existent pet in the store
30+
content:
31+
application/json:
32+
schema:
33+
$ref: '#/components/schemas/Pet'
34+
required: true
35+
components:
36+
schemas:
37+
Pet:
38+
required:
39+
- name
40+
- photoUrls
41+
type: object
42+
properties:
43+
id:
44+
type: integer
45+
format: int64
46+
example: 10
47+
leak:
48+
type: string
49+
default:
50+
$ref: '/etc/passwd'
51+
name:
52+
type: string
53+
example: doggie
54+
xml:
55+
name: pet
56+
```
57+
58+
The following example uses swagger-parser to process the above document.
59+
60+
```
61+
import SwaggerParser from '@apidevtools/swagger-parser';
62+
63+
const documentSource = './document-shown-above.yml';
64+
const doc = await SwaggerParser.dereference(documentSource);
65+
console.log(doc.paths['/pet'].put.requestBody.content['application/json'].schema);
66+
```
67+
68+
A snippet of the resolved document is shown below.
69+
70+
```
71+
{
72+
required: [ 'name', 'photoUrls' ],
73+
type: 'object',
74+
properties: {
75+
id: { type: 'integer', format: 'int64', example: 10 },
76+
leak: {
77+
type: 'string',
78+
default: 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false root:*:0:0:System Administrator:/var/root:/bin/sh daemon:*:1:1:System Services:/var/root:/usr/bin/false _uucp:*:4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico _taskgated:*:13:13:Task Gate Daemon:/var/empty:/usr/bin/false _networkd:*:24:24:Network Services:/var/networkd:/usr/bin/false _installassistant:*:25:25:Install Assistant:/var/empty:/usr/bin/false _lp:*
79+
```
80+
81+
You can mitigate the discussed behaviour by putting restrictions on file extensions and being mindful of the environment the service is running in. The following sections will go into more detail on these.
82+
83+
### Restrictions based on File Extension
84+
85+
You can and should configure the file resolver to only process YAML and JSON files. An example of how you can do this is shown below.
86+
87+
```
88+
const doc = await SwaggerParser.dereference(documentSource, {
89+
resolve: {
90+
file: {
91+
canRead: ['.yml', '.json']
92+
}
93+
}
94+
});
95+
```
96+
97+
As a result, any attempt to resolve files other than YAML and JSON will result in the following error.
98+
99+
```
100+
SyntaxError: Unable to resolve $ref pointer "/etc/passwd"
101+
at onError (node_modules/@apidevtools/json-schema-ref-parser/lib/parse.js:85:20) {
102+
toJSON: [Function: toJSON],
103+
[Symbol(nodejs.util.inspect.custom)]: [Function: inspect]
104+
}
105+
```
106+
107+
Configuring the file resolver this way only partially mitigates LFI. See the next section for additional considerations.
108+
109+
### Environmental Considerations
110+
111+
With the previously mentioned mitigation in place, an attacker could still craft a malicious OpenAPI document to make the library read arbitrary JSON or YAML files on the filesystem and potentially gain access to sensitive data (e.g. credentials). This is possible if:
112+
113+
* The actor knows (or successfully guesses) the location of a JSON or YAML file on the file system
114+
* The service using the library has privileges to read the file
115+
* The service using the library sends requests to the server specified in the OpenAPI document
116+
117+
You can prevent exploitation by hardening the environment in which the service is running:
118+
119+
* The service should run under its own dedicated user account
120+
* File system permissions should be configured so that the service cannot read any YAML or JSON files not owned by the service user
121+
122+
If you have any YAML or JSON files the service must have access to that may contain sensitive information, such as configuration file(s), you must take additional measures to prevent exploitation. A non-exhaustive list:
123+
124+
* You can implement your service so that it reads the configuration into memory at start time, then uses [setuid](https://nodejs.org/api/process.html#processsetuidid) and [setgid](https://nodejs.org/api/process.html#processsetgidid) to set the process' UID and GID to the ID of a user and ID of a group that has no access to the file on the filesystem
125+
* Do not store sensitive information, such as credentials, in the service configuration files

0 commit comments

Comments
 (0)