Skip to content

Instantly share code, notes, and snippets.

@v1nc
Last active November 11, 2022 09:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save v1nc/f376000496fd16362b86c0910962284b to your computer and use it in GitHub Desktop.
Save v1nc/f376000496fd16362b86c0910962284b to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from pathlib import Path
import json
# list for solutions
solutions = [0,0,0,0,0,0,0,0]
# iterate over all API files
pathlist = Path('openapi-in-the-wild').glob('*.json')
for file_path in pathlist:
# load API JSON file
f = open(str(file_path))
data = json.load(f)
# parse results
# task 1
# read openapi version
if 'openapi' in data and data['openapi'] == '3.1.0':
solutions[0]+=1
# task 2
# read openapi version and check if <3
if 'swagger' in data:
version = data['swagger'].split('.')[0]
# version in 'swagger' should be <3, check anyway
try:
version = int(version)
if version < 3:
solutions[1]+=1
except:
pass
# task 3
# check if length of servers is > 2
if 'servers' in data and len(data['servers']) > 2:
solutions[2]+=1
# task 4
if 'paths' in data:
found = False
# iterate over every path
for path in data['paths']:
# stop if result was found for this API specification
if not found:
# iterate over every method of the path
for method in data['paths'][path]:
# sometimes 'path' is only a string
if not found and isinstance(data['paths'][path], dict):
# sometimes 'method' value is only a bool
if ((isinstance(data['paths'][path][method], dict)
or isinstance(data['paths'][path][method], list))
and 'requestBody' in data['paths'][path][method]):
# check the content of the request body
if 'content' in data['paths'][path][method]['requestBody']:
supports_json = False
supports_xml = False
# check if json + xml is supported for the request
for input_type in data['paths'][path][method]['requestBody']['content']:
if 'json' in input_type:
supports_json = True
elif 'xml' in input_type:
supports_xml = True
if supports_xml and supports_json:
solutions[3]+=1
found = True
# task 5 + 6 + 7
if 'components' in data and 'securitySchemes' in data['components']:
http_found = False
api_key_found = False
not_best_practice_found = False
# check every security scheme
for security_scheme in data['components']['securitySchemes']:
if 'type' in data['components']['securitySchemes'][security_scheme]:
# check if the type of the security scheme is 'http', for task 5
if not http_found and data['components']['securitySchemes'][security_scheme]['type'] == 'http':
solutions[4]+=1
# check if the type of the security scheme is 'apiKey', for task 6
elif not api_key_found and data['components']['securitySchemes'][security_scheme]['type'] == 'apiKey':
solutions[5]+=1
# if the type is 'apiKey', check if the API key is send with the query (bad practice), for task 7
if not not_best_practice_found and data['components']['securitySchemes'][security_scheme]['in'] == 'query':
solutions[6]+=1
# also check if the API key is send with the cookie (not best practice), for task 7
elif not not_best_practice_found and data['components']['securitySchemes'][security_scheme]['in'] == 'cookie':
solutions[6]+=1
# task 8
if 'paths' in data:
found = False
# iterate over every path (again)
for path in data['paths']:
if not found:
# iterate over every method of the path
for method in data['paths'][path]:
# sometimes 'path' is only a string
if not found and isinstance(data['paths'][path], dict):
# sometimes 'method' value is only a bool
if ((isinstance(data['paths'][path][method], dict)
or isinstance(data['paths'][path][method], list))):
# check if the top-level authentication schemes are overwritten by the path security
# if the 'security' list is empty, authentication is disabled
if ('security' in data['paths'][path][method]
and len(data['paths'][path][method]['security']) == 0):
solutions[7]+=1
found = True
# print result
print(f'1. How many APIs define OpenAPI 3.1.0? {solutions[0]}')
print(f'2. How many APIs define OpenAPI older than 3.0.0? {solutions[1]}')
print(f'3. How many APIs define multiple servers? {solutions[2]}')
print(f'4. How many APIs do have paths that support both JSON and XML as input in the request? {solutions[3]}')
print(f'5. How many APIs support ”HTTP” Authentication? {solutions[4]}')
print(f'6. How many APIs support ”API Key” Authentication? {solutions[5]}')
print(f'7. How many APIs deviate from the recommended security best current practices regarding API keys? {solutions[6]}')
print(f'8. How many APIs do have paths that overwrite the defined top-level authentication scheme(s) and completely disable the authentication? {solutions[7]}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment