Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Bug Report
description: Report an error or inconsistency in the standard
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report an issue with the TCASVS.
- type: input
id: location
attributes:
label: Location
description: Which chapter, section, or requirement ID is affected?
placeholder: "e.g., V3.2.1 or 0x12-V3-Data-Storage-and-Protection.md"
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: Describe the issue clearly.
placeholder: What is wrong and what should it say instead?
validations:
required: true
- type: dropdown
id: type
attributes:
label: Issue type
options:
- Incorrect requirement text
- Missing CWE mapping
- Incorrect level assignment
- Formatting/layout issue
- Broken link
- Other
validations:
required: true
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: OWASP Slack
url: https://owasp.slack.com
about: Join the OWASP Slack workspace to discuss the TCASVS with the community
48 changes: 48 additions & 0 deletions .github/ISSUE_TEMPLATE/new-requirement.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: New Requirement Proposal
description: Propose a new security requirement for inclusion in the TCASVS
labels: ["enhancement", "new-requirement"]
body:
- type: markdown
attributes:
value: |
Use this template to propose a new requirement. Please provide enough context for the working group to evaluate the proposal.
- type: input
id: chapter
attributes:
label: Target Chapter
description: Which chapter should this requirement belong to?
placeholder: "e.g., V3 Data Storage and Protection"
validations:
required: true
- type: textarea
id: requirement
attributes:
label: Proposed Requirement
description: Write the requirement in TCASVS format (start with "Verify that...").
placeholder: "Verify that the application..."
validations:
required: true
- type: dropdown
id: level
attributes:
label: Suggested Level
description: At which verification level should this apply?
options:
- L1 (all applications)
- L2 (sensitive data)
- L3 (high security)
validations:
required: true
- type: textarea
id: rationale
attributes:
label: Rationale
description: Why is this requirement needed? Reference attack scenarios, CWEs, or real-world incidents.
validations:
required: true
- type: input
id: cwe
attributes:
label: CWE Mapping
description: Related CWE ID(s) if known.
placeholder: "e.g., CWE-312"
96 changes: 74 additions & 22 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,69 +1,121 @@
name: Convert Markdown to PDF and Create Release
name: Build and Release TCASVS

on:
push:
branches:
- main
paths:
- '5.0/en/**'
- '5.0/tools/**'
- '5.0/Makefile'

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v4

- name: Set up Pandoc and jq
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y pandoc texlive jq
sudo apt-get install -y pandoc texlive-xetex texlive-fonts-recommended jq

- name: Install Python dependencies
run: pip install dicttoxml2

- name: Verify requirements parse correctly
working-directory: 5.0
run: |
python tools/export.py --verify-only --format json --language en
python tools/export.py --verify-only --format csv --language en

- name: Fetch the latest release
- name: Build all exports
working-directory: 5.0
run: make all

- name: Fetch the latest release tag
id: fetch_latest_release
run: |
LATEST_TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name)
if [ -z "$LATEST_TAG" ] || [ "$LATEST_TAG" == "null" ]; then
LATEST_TAG="v0.4.0"
fi
# using this to fake/bump versions to v1.0
if [ "$LATEST_TAG" == "v0.4.0" ]; then
LATEST_TAG="v1.0"
LATEST_TAG="v5.0.0"
fi
echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV

- name: Increment version
id: increment_version
run: |
LATEST_TAG=${{ env.LATEST_TAG }}
echo "Latest tag: $LATEST_TAG"
LATEST_VERSION=${LATEST_TAG#v}
IFS='.' read -r major minor <<< "$LATEST_VERSION"
NEW_VERSION="$major.$((minor + 1))"
IFS='.' read -r major minor patch <<< "$LATEST_VERSION"
NEW_VERSION="$major.$minor.$((patch + 1))"
NEW_TAG="v$NEW_VERSION"
echo "New version: $NEW_TAG"
echo "NEW_TAG=$NEW_TAG" >> $GITHUB_ENV

- name: Concatenate and Convert Markdown to PDF
run: |
pandoc document/1.0/*.md -o TASVS-${{ env.NEW_TAG }}.pdf -V geometry:margin=2cm

- name: Create GitHub Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.NEW_TAG }}
release_name: Release ${{ env.NEW_TAG }}
release_name: TCASVS ${{ env.NEW_TAG }}
draft: false
prerelease: false

- name: Upload PDF to Release
- name: Upload PDF
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./TASVS-${{ env.NEW_TAG }}.pdf
asset_name: TASVS-${{ env.NEW_TAG }}.pdf
asset_path: ./5.0/dist/OWASP_Thick_Client_Application_Security_Verification_Standard_5.0.0_en.pdf
asset_name: TCASVS-${{ env.NEW_TAG }}.pdf
asset_content_type: application/pdf

- name: Upload DOCX
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./5.0/dist/OWASP_Thick_Client_Application_Security_Verification_Standard_5.0.0_en.docx
asset_name: TCASVS-${{ env.NEW_TAG }}.docx
asset_content_type: application/vnd.openxmlformats-officedocument.wordprocessingml.document

- name: Upload JSON
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./5.0/dist/OWASP_Thick_Client_Application_Security_Verification_Standard_5.0.0_en.json
asset_name: TCASVS-${{ env.NEW_TAG }}.json
asset_content_type: application/json

- name: Upload CSV
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./5.0/dist/OWASP_Thick_Client_Application_Security_Verification_Standard_5.0.0_en.csv
asset_name: TCASVS-${{ env.NEW_TAG }}.csv
asset_content_type: text/csv

- name: Upload CycloneDX
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./5.0/dist/OWASP_Thick_Client_Application_Security_Verification_Standard_5.0.0_en.cdx.json
asset_name: TCASVS-${{ env.NEW_TAG }}.cdx.json
asset_content_type: application/json
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/Gemfile
/Gemfile.lock
/favicon.ico
_site/
_site/
__pycache__/
*.pyc
22 changes: 22 additions & 0 deletions .markdownlint.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"default": true,
"MD013": {
"line_length": 500,
"tables": false
},
"MD024": {
"siblings_only": true
},
"MD033": {
"allowed_elements": [
"a",
"img",
"div",
"b",
"sup",
"u",
"br"
]
},
"MD041": false
}
97 changes: 97 additions & 0 deletions 5.0/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# TCASVS Build System
# Generates PDF, DOCX, JSON, CSV, XML, and CycloneDX outputs from source Markdown.

PROJDIR := $(realpath $(CURDIR))
TOOLSDIR := tools
TEMPLATEDIR := templates
SOURCEDIR := en
BUILDDIR := build
DISTDIR := dist

TARGETNAME := OWASP_Thick_Client_Application_Security_Verification_Standard_5.0.0_

# Source files
SOURCE_FILES := $(sort $(wildcard $(SOURCEDIR)/0x*.md $(SOURCEDIR)/0x*.yaml))
BUILD_FILES := $(patsubst $(SOURCEDIR)/%, $(BUILDDIR)/%, $(SOURCE_FILES))

# Output targets
MD_FILE := $(DISTDIR)/$(TARGETNAME)en.md
PDF_FILE := $(DISTDIR)/$(TARGETNAME)en.pdf
DOCX_FILE := $(DISTDIR)/$(TARGETNAME)en.docx
JSON_FILE := $(DISTDIR)/$(TARGETNAME)en.json
JSON_FLAT_FILE := $(DISTDIR)/$(TARGETNAME)en.flat.json
CSV_FILE := $(DISTDIR)/$(TARGETNAME)en.csv
XML_FILE := $(DISTDIR)/$(TARGETNAME)en.xml
CDX_FILE := $(DISTDIR)/$(TARGETNAME)en.cdx.json

EXPORT_TOOL := $(TOOLSDIR)/export.py

# Pandoc flags
PANDOC_PDF_FLAGS := -f markdown -s -t latex --pdf-engine=xelatex
PANDOC_DOCX_FLAGS := -s -t docx -f markdown --toc --columns 10000 \
--reference-doc=$(TEMPLATEDIR)/reference.docx

.PHONY: all pdf docx json json_flat csv xml cdx_json md clean verify

all: md pdf docx json json_flat csv xml cdx_json

$(BUILDDIR):
mkdir -p $@

$(DISTDIR):
mkdir -p $@

# Transform source MD (add CWE hyperlinks, fix image paths)
$(BUILDDIR)/%.md: $(SOURCEDIR)/%.md | $(BUILDDIR)
sed -E 's#(\| ?)([0-9]{2,4})( ?\|)#\1[\2](https://cwe.mitre.org/data/definitions/\2.html)\3#g' $< > $@

$(BUILDDIR)/%.yaml: $(SOURCEDIR)/%.yaml | $(BUILDDIR)
cp $< $@

# Merged Markdown
md: $(MD_FILE)
$(MD_FILE): $(BUILD_FILES) | $(DISTDIR)
pandoc -f gfm -s -t markdown -o $@ $(BUILDDIR)/0x*.md

# PDF via LaTeX
pdf: $(PDF_FILE)
$(PDF_FILE): $(BUILD_FILES) | $(DISTDIR)
pandoc $(PANDOC_PDF_FLAGS) \
--include-in-header=$(TEMPLATEDIR)/header-eisvogel.tex \
-o $@ --template $(TEMPLATEDIR)/eisvogel.tex \
$(BUILDDIR)/0x*.md $(SOURCEDIR)/0x00-Header.yaml

# DOCX
docx: $(DOCX_FILE)
$(DOCX_FILE): $(BUILD_FILES) | $(DISTDIR)
pandoc $(PANDOC_DOCX_FLAGS) -o $@ $(BUILDDIR)/0x*.md $(SOURCEDIR)/0x00-Header.yaml

# Structured exports via Python
json: $(JSON_FILE)
$(JSON_FILE): $(SOURCE_FILES) | $(DISTDIR)
cd $(PROJDIR) && python3 $(EXPORT_TOOL) --format json --language $(SOURCEDIR) > $@

json_flat: $(JSON_FLAT_FILE)
$(JSON_FLAT_FILE): $(SOURCE_FILES) | $(DISTDIR)
cd $(PROJDIR) && python3 $(EXPORT_TOOL) --format json_flat --language $(SOURCEDIR) > $@

csv: $(CSV_FILE)
$(CSV_FILE): $(SOURCE_FILES) | $(DISTDIR)
cd $(PROJDIR) && python3 $(EXPORT_TOOL) --format csv --language $(SOURCEDIR) > $@

xml: $(XML_FILE)
$(XML_FILE): $(SOURCE_FILES) | $(DISTDIR)
cd $(PROJDIR) && python3 $(EXPORT_TOOL) --format xml --language $(SOURCEDIR) > $@

cdx_json: $(CDX_FILE)
$(CDX_FILE): $(SOURCE_FILES) | $(DISTDIR)
cd $(PROJDIR) && python3 $(EXPORT_TOOL) --format cdx_json --language $(SOURCEDIR) > $@

# Verification
verify: $(SOURCE_FILES)
cd $(PROJDIR) && python3 $(EXPORT_TOOL) --verify-only --format json --language $(SOURCEDIR)
cd $(PROJDIR) && python3 $(EXPORT_TOOL) --verify-only --format csv --language $(SOURCEDIR)

# Clean
clean:
rm -rf $(BUILDDIR) $(DISTDIR)
26 changes: 26 additions & 0 deletions 5.0/docs_en/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Compiled Outputs

This directory contains auto-generated output files for the TCASVS standard.

## Available Formats

The following formats are generated by the CI pipeline and attached to GitHub Releases:

- **PDF** — Paginated document for offline reading
- **DOCX** — Editable Word format for review workflows
- **CSV** — Flat requirement list for spreadsheet tooling
- **JSON** — Machine-readable structured export
- **CycloneDX JSON** — SBOM-compatible requirement representation

## Generating Locally

```bash
cd ../
make
```

Output files will be placed in `dist/`. See [COMPILING.md](../../COMPILING.md) for full instructions.

## Note

Do not commit generated files to this directory manually. They are produced by the `main.yml` GitHub Actions workflow and published as release artifacts.
Loading