{"id":34087810,"url":"https://github.com/victorazzam/demal","last_synced_at":"2026-04-20T08:04:16.342Z","repository":{"id":63568677,"uuid":"567410174","full_name":"victorazzam/demal","owner":"victorazzam","description":"Encode and decode MAL (Meta Attack Language) to and from JSON.","archived":false,"fork":false,"pushed_at":"2023-07-30T08:12:21.000Z","size":279,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-27T16:02:17.486Z","etag":null,"topics":["cli","command-line-tool","decoder","encoder","json","library","meta-attack-language","mitre-attack","parser","python","python3"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/demal","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/victorazzam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-11-17T18:22:58.000Z","updated_at":"2025-07-16T22:03:31.000Z","dependencies_parsed_at":"2023-01-30T15:16:03.187Z","dependency_job_id":null,"html_url":"https://github.com/victorazzam/demal","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/victorazzam/demal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victorazzam%2Fdemal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victorazzam%2Fdemal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victorazzam%2Fdemal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victorazzam%2Fdemal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/victorazzam","download_url":"https://codeload.github.com/victorazzam/demal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victorazzam%2Fdemal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27729186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-14T02:00:11.348Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-line-tool","decoder","encoder","json","library","meta-attack-language","mitre-attack","parser","python","python3"],"created_at":"2025-12-14T13:54:27.716Z","updated_at":"2025-12-14T13:54:28.222Z","avatar_url":"https://github.com/victorazzam.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [demal](https://github.com/victorazzam/demal)\n\n[![PyPI](https://img.shields.io/pypi/v/demal?logo=git\u0026style=flat)](https://pypi.python.org/pypi/demal)\n[![Build](https://github.com/victorazzam/demal/actions/workflows/python-package.yml/badge.svg)](https://github.com/victorazzam/demal/actions/workflows/python-package.yml)\n[![Python](https://img.shields.io/pypi/pyversions/demal?logo=python\u0026logoColor=yellow)](https://www.python.org/doc/versions/)\n[![License](https://img.shields.io/github/license/victorazzam/demal)](https://github.com/victorazzam/demal/blob/master/LICENSE.txt)\n\n#### MAL (Meta Attack Language) to JSON encoding/decoding library and command-line tool.\n\nConvert from MAL to JSON and, as of version 2, from JSON to MAL. Incompatible with the [official tool](https://github.com/mal-lang/mal2json).\n\n## Info\n\n**Author:** Victor Azzam\n\n**License:** MIT\n\n**Latest version:** `2.1.1`\n\n**Requires:** Python 3.8 or later\n\n**Batteries included:** Tests and examples are provided in this repository.\n\n## Contents\n\n- [Usage](#usage)\n- [Output](#output)\n- [Limitations](#limitations)\n- [Resources](#resources)\n\n## Usage\n\n### Install\n```shell\n~ pip install demal\n```\n\n#### or\n\n### Install from source\n```shell\n~ git clone https://github.com/victorazzam/demal\n~ cd demal \u0026\u0026 pip install .\n```\n\n### General usage\n![https://raw.githubusercontent.com/victorazzam/demal/main/usage.jpg](usage.jpg)\n\n### Convert `file.mal` to `file.mal.json`\n```shell\n~ demal file.mal\n```\n\n### Convert `file.mal` to `file.json`\n```shell\n~ demal file.mal file.json\n```\n\n### Convert `file.json` to `file.mal` (if JSON abides by [demal's output](#output))\n```shell\n~ demal file.json file.mal -r\n```\n\n### Convert `file.mal` and print it out\n```shell\n~ demal file.mal -\n```\n\n### Read from standard input, convert, and print it out\n```shell\n~ cat file.mal | demal - -\n```\n\n### Read from standard input, convert, and write to `out.json`\n```shell\n~ cat file.mal | demal - out.json\n```\n\n### Convert several files and view them interactively\n```shell\n~ cat file1.mal file2.mal | demal - - | less\n```\n\n### Display debugging information while converting\n```shell\n~ demal tests/test2.mal debug\nparse got: '#id: \"tmp\"'\nparse got: '#version: \"0.0.0\"'\nparse got: 'category C1 {'\nparse_category got: '}'\nparse got: 'category C2'\nparse_header got: 'user info: \"info\"'\nparse_header got: '{'\nparse_category got: 'asset A1 {'\nparse_asset got: '\u0026 At1'\nparse_asset got: '| At2'\n# output truncated\n```\n\n### Use it as a Python module\n```py\nfrom demal import MalParser\nmal = MalParser('threat-model.mal')\nmal.debug = True\nmal.parse() # displays debugging messages due to the previous line\n# output suppressed\n\nmal.dump(out='parsed.json', pretty=True) # beautify and save to parsed.json\nprint(mal) # pretty-prints the json object\n{\n  \"associations\": [\n    {\n      \"asset_l\": \"Server\",\n      \"asset_l\": \"Client\",\n# output truncated\n```\n\n#### Merge multiple instances by addition (or multiplication or bitwise-or) akin to using `include`\nCheck `tests/test-lib.py`:\n\n```py\nfrom demal import MalParser, sys\n\nprint('Parse and combine two test files.')\nm1, m2 = MalParser('test1.mal'), MalParser('test2.mal')\nm1.parse()\nm2.parse()\n\nprint('First:', m1['version'])\n# First: 1.0.0\n\nprint('Second:', m2['version'])\n# Second: 0.0.0\n\nm = m1 + m2 # combine category/association items, same as \"include\"\nprint('Combined:', m['version'])\n# Combined: 0.0.0\n\nprint('\\nModify variable.')\nv = {'version': '1.3.3.7'}\nm += v\nprint('New version:', m['version'])\n# New version: 1.3.3.7\n\nprint('\\nChange inner dictionary data.')\nprint('Before:', m['categories']['System']['assets']['Host']['attributes']['guessedPassword']['probability'])\n# Before: Exponential(0.02)\n\nm['categories']['System']['assets']['Host']['attributes']['guessedPassword']['probability'] = 'abc'\nprint('After:', m['categories']['System']['assets']['Host']['attributes']['guessedPassword']['probability'])\n# After: abc\n\nprint('\\nList assets with dot notation: category.asset')\nprint('m1:', list(m1))\nprint('m2:', list(m2))\nprint('m (m1+m2):', list(m))\n# m1: ['System.Host', 'System.Network', 'System.Password', 'System.User']\n# m2: ['C2.A1', 'C2.A2', 'C2.A3', 'C2.A4', 'C2.A5', 'C2.A6', 'C3.A1', 'C4.A1', 'C5.distribution']\n# m (m1+m2): ['System.Host', 'System.Network', 'System.Password', 'System.User', 'C2.A1', 'C2.A2', 'C2.A3', 'C2.A4', 'C2.A5', 'C2.A6', 'C3.A1', 'C4.A1', 'C5.distribution']\n\nprint('\\nConvert JSON back to MAL syntax.')\nm.dump_mal(out = sys.stdout)\n# Output redacted\n```\n\n## Output\nThe following output JSON structure is produced (\"*quotes*\" are placeholders, `monospace` shows exact values, | denotes \"choose one of\"):\n\n- Array: `associations`\n  - Object:\n    - Object: `meta`\n      - String: \"*key*\"\n        - String: \"*value*\"\n    - String: `asset_l`, `field_l`, `mult_l`, `name`, `mult_r`, `field_r`, `asset_r`\n- Object: `categories`\n  - Object: \"*category name*\"\n    - Object: `meta`\n      - String: \"*key*\"\n        - String: \"*value*\"\n    - Object: `assets`\n      - Object: `meta`\n        - String: \"*key*\"\n          - String: \"*value*\"\n      - Object: \"*asset name*\"\n        - Boolean: `abstract`\n        - Object: `attributes`\n          - Object: \"*attribute name*\"\n            - Array: `cia`\n              - String (length=1): `C` | `I` | `A` (MAL: `{CIA}`)\n            - Object: `meta`\n              - String: \"*key*\"\n                - String: \"*value*\"\n            - String: `probability`\n              - String (nullable): one of several probability distributions [outlined here](https://github.com/mal-lang/mal-documentation/wiki/MAL-Syntax#probability-distributions)\n            - Array: `tags`\n              - String: `hidden` | `debug` | `trace` (MAL: `@hidden` `@debug` `@trace`)\n            - String: `type`\n              - String: `or` | `and` | `defense` | `exists` | `lacks` (MAL: `|` `\u0026` `#` `E` `!E`)\n            - Object: `append` | `leads_to` | `require` (MAL: `+\u003e` `-\u003e` `\u003c-`)\n              - String: \"*key or number*\"\n                - String: \"*expression or action*\"\n        - String: `extends`\n          - String (nullable): \"*asset to be extended*\"\n        - Object: `meta`\n          - String: \"*key*\"\n            - String: \"*value*\"\n\nExample:\n\n```py\n{\n  \"associations\": [\n    {\n      \"asset_l\": \"left_asset\",\n      \"asset_r\": \"right_asset\",\n      \"field_l\": \"left_field\",\n      \"field_r\": \"right_field\",\n      \"meta\": {\n        \"key\": \"value\"\n        # ...\n      },\n      \"mult_l\": \"left_multiplier\",\n      \"mult_r\": \"right_multiplier\",\n      \"name\": \"Association\"\n    } # ...\n  ],\n  \"categories\": {\n    \"Category1\": {\n      \"assets\": {\n        \"Asset1\": {\n          \"abstract\": false,\n          \"attributes\": {\n            \"access\": {\n              \"cia\": [\"C\", \"A\"],\n              \"meta\": {},\n              \"probability\": \"Exponential(0.02)\", # etc, or simply null\n              \"tags\": [],\n              \"type\": \"and\"\n            },\n            \"authenticate\": {\n              \"cia\": null,\n              \"leads_to\": {\n                \"0\": \"access\",\n                \"a\": \"b \\\\/ c \" # result of: let a = ...\n              },\n              \"meta\": {},\n              \"probability\": null,\n              \"tags\": [\n                \"hidden\",\n                \"debug\",\n                \"trace\"\n              ],\n              \"type\": \"or\"\n            } # ...\n          },\n          \"extends\": null,\n          \"meta\": {}\n        } # ...\n      },\n      \"meta\": {}\n    }\n  },\n  \"id\": \"org.name.project\",\n  \"version\": \"1.0.0\"\n}\n```\n\nWhen converting to MAL the output should closely resemble the original, albeit more concise.\n\n## Limitations\n - [X] ~Multi-line comments should be avoided.~\n - [ ] Quotation marks must not be escaped.\n - [ ] Expects clean spec-compliant code.\n\n## Resources\n - **Example:** [exampleLang/src/main/mal/exampleLang.mal](https://github.com/mal-lang/exampleLang/blob/master/src/main/mal/exampleLang.mal)\n - **Spec:** [malcompiler/wiki/MAL-language-specification](https://github.com/mal-lang/malcompiler/wiki/MAL-language-specification)\n - **Syntax:** [mal-documentation/wiki/MAL-Syntax](https://github.com/mal-lang/mal-documentation/wiki/MAL-Syntax)\n - **Reference:** [malcompiler-lib/src/main/java/org/mal_lang/compiler/lib/Lexer.java](https://github.com/mal-lang/malcompiler/blob/master/malcompiler-lib/src/main/java/org/mal_lang/compiler/lib/Lexer.java)\n - **Guide:** [https://nse.digital/...](https://nse.digital/pages/guides/Creating%20threat%20models/MAL.html)\n - **MAL author video:** [https://play.kth.se/...](https://play.kth.se/media/t/0_ckc2056q)\n - **Project page:** [https://www.kth.se/...](https://www.kth.se/cs/nse/research/software-systems-architecture-and-security/projects/mal-the-meta-attack-language-1.922174)\n - **Research paper:** [https://dl.acm.org/doi/10.1145/3230833.3232799](https://dl.acm.org/doi/10.1145/3230833.3232799)\n - **Official MAL to JSON converter:** [mal2json](https://github.com/mal-lang/mal2json)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvictorazzam%2Fdemal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvictorazzam%2Fdemal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvictorazzam%2Fdemal/lists"}