{"id":13599073,"url":"https://github.com/tw4l/brunnhilde","last_synced_at":"2025-05-07T15:46:13.049Z","repository":{"id":45014305,"uuid":"49334861","full_name":"tw4l/brunnhilde","owner":"tw4l","description":"Siegfried-based characterization tool for directories and disk images","archived":false,"fork":false,"pushed_at":"2024-12-15T16:10:37.000Z","size":7567,"stargazers_count":84,"open_issues_count":12,"forks_count":11,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-05-03T04:05:22.747Z","etag":null,"topics":["archives","code4lib","digital-preservation","disk-image","format-identification","pronom"],"latest_commit_sha":null,"homepage":"","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/tw4l.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-01-09T17:53:20.000Z","updated_at":"2024-11-14T19:14:21.000Z","dependencies_parsed_at":"2023-10-20T17:41:34.216Z","dependency_job_id":null,"html_url":"https://github.com/tw4l/brunnhilde","commit_stats":{"total_commits":497,"total_committers":6,"mean_commits":82.83333333333333,"dds":"0.16901408450704225","last_synced_commit":"e4d9b523b8060681b08be3743fef94147c700ea0"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tw4l%2Fbrunnhilde","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tw4l%2Fbrunnhilde/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tw4l%2Fbrunnhilde/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tw4l%2Fbrunnhilde/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tw4l","download_url":"https://codeload.github.com/tw4l/brunnhilde/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252908949,"owners_count":21823524,"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","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":["archives","code4lib","digital-preservation","disk-image","format-identification","pronom"],"created_at":"2024-08-01T17:00:59.461Z","updated_at":"2025-05-07T15:46:13.023Z","avatar_url":"https://github.com/tw4l.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"## Brunnhilde - Siegfried-based characterization tool for directories and disk images\n\n### Version: Brunnhilde 1.9.6\n\nGenerates aggregate reports of files in a directory or disk image based on input from Richard Lehane's [Siegfried](http://www.itforarchivists.com/siegfried).  \n\nFor the graphical user interface (GUI) version of Brunnhilde, see [Brunnhilde GUI](https://github.com/tw4l/brunnhilde-gui).   \n\nBrunnhilde runs Siegfried against a specified directory or disk image, loads the results into a sqlite3 database, and queries the database to generate reports to aid in triage, arrangement, and description of digital archives. The program will also check for viruses unless specified otherwise, and will optionally run bulk_extractor against the given source. Outputs include:  \n\n* `report.html`: Includes some provenance information on the scan itself, aggregate statistics for the material as a whole (number of files, begin and end dates, number of unique vs. duplicate files, etc.), and detailed reports on content found (file formats, file format versions, MIME types, last modified dates by year, unidentified files, Siegfried warnings/errors, duplicate files, and -optionally - Social Security Numbers found by bulk_extractor).\n* `csv_reports` folder: Contains CSV results queried from database on file formats, file format versions, MIME types, last modified dates by year, unidentified files, Siegfried warnings and errors, and duplicate files.  \n* `siegfried.csv`: Full CSV output from Siegfried  \n\nOptionally, outputs may also include:  \n\n* `tree.txt`: Tree report of the directory structure of directory or file system on disk image (in Linux and macOS only)  \n* `bulk_extractor` folder: Contains bulk_extractor outputs (if selected).  \n* `carved_files` folder: Contains files carved from disk images by tsk_recover or HFS Explorer (generated in `-d` mode; can be deleted at end of process by passing the `-r` or `--removefiles` flag to Brunnhilde).  \n* `dfxml.xml`: A fiwalk-generated [Digital Forensics XML](http://www.forensicswiki.org/wiki/Category:Digital_Forensics_XML) file describing the volumes, filesystems, and files on a disk (generated in -d mode for non-HFS disk images).  \n* `logs` folder: Contains log files for ClamAV and bulk_extractor (if selected).  \n* `siegfried.sqlite`: SQLite3 database generated from Siegfried CSV (deleted at end of processing by default, but may be retained by using the `-k` flag.)\n\nAll outputs are placed into a new directory named after the identifier passed to Brunnhilde as the last argument.  \n\nFor the most accurate statistics with Siegfried 1.6+, it is advised to force Siegfried to make single identifications for files with multiple filetypes. This can be accomplished with roy using the following command:  \n\n```\nroy build -multi 0  \n```  \n\nFor a more detailed explanation of how multiple identifications are handled by Siegfried, see [https://github.com/richardlehane/siegfried/issues/75](https://github.com/richardlehane/siegfried/issues/75).  \n\n### Installation  \n\nBrunnhilde and all of its dependencies are already installed in BitCurator version 1.7.106+. In versions 1.8.0+, a terminal launcher for Brunnhilde is included in the \"Forensics and Reporting\" folder on the BitCurator desktop.  \n\nBrunnhilde minimally requires that Python 2 or 3 and Siegfried are installed on your system to characterize directories of content. Characterizing disk images introduces additional dependencies. For more information, see [Dependencies](https://github.com/tw4l/brunnhilde#dependencies).  \n\n`sudo pip install brunnhilde`\n\nIf using macOS, you may have to run `sudo pip3 install brunnhilde`\n\nOnce installed, you can call brunnhilde with just `brunnhilde.py [arguments]`.  \n\nIf an older version of Brunnhilde is installed on your system, you can upgrade to the latest version with:  \n\n`sudo pip install brunnhilde --upgrade`  \n\n\n### Usage\n\n```  \nusage: brunnhilde.py [-h] [-a] [-b] [--ssn_mode SSN_MODE] [--regex REGEX] [-d]\n                     [--hfs] [--hfs_resforks] [--hfs_partition HFS_PARTITION]\n                     [--hfs_fsroot HFS_FSROOT] [--tsk_imgtype TSK_IMGTYPE]\n                     [--tsk_fstype TSK_FSTYPE]\n                     [--tsk_sector_offset TSK_SECTOR_OFFSET] [--hash HASH]\n                     [-k] [-l] [-n] [-r] [-t] [-v] [-V] [-w] [-z]\n                     [--save_assets SAVE_ASSETS] [--load_assets LOAD_ASSETS]\n                     [--csv CSV] [--stdin] [-o] [--in-memory-db]\n                     source destination [basename]\n\npositional arguments:\n  source                Path to source directory or disk image\n  destination           Path to destination for reports\n  basename              DEPRECATED. Accession number or identifier, used as\n                        basename for outputs. Prefer using the new simpler\n                        `brunnhilde.py source destination` syntax. The\n                        basename argument is retained for API stability and\n                        used when provided.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -a, --allocated       Instruct tsk_recover to export only allocated files\n                        (recovers all files by default)\n  -b, --bulkextractor   Run Bulk Extractor on source\n  --ssn_mode SSN_MODE   Specify ssn_mode for Bulk Extractor (0, 1, or 2)\n  --regex REGEX         Specify path to regex file\n  -d, --diskimage       Use disk image instead of dir as input (Linux and\n                        macOS only)\n  --hfs                 Use for raw disk images of HFS disks\n  --hfs_resforks, --resforks\n                        HFS option: Extract AppleDouble resource forks from\n                        HFS disks\n  --hfs_partition HFS_PARTITION\n                        HFS option: Specify partition number as integer for\n                        unhfs to extract (e.g. --hfs_partition 1)\n  --hfs_fsroot HFS_FSROOT\n                        HFS option: Specify POSIX path (file or dir) in the\n                        HFS file system for unhfs to extract (e.g.\n                        --hfs_fsroot /Users/tessa/backup/)\n  --tsk_imgtype TSK_IMGTYPE\n                        TSK option: Specify format of image type for\n                        tsk_recover. See tsk_recover man page for details\n  --tsk_fstype TSK_FSTYPE\n                        TSK option: Specify file system type for tsk_recover.\n                        See tsk_recover man page for details\n  --tsk_sector_offset TSK_SECTOR_OFFSET\n                        TSK option: Sector offset for particular volume for\n                        tsk_recover to recover\n  --hash HASH           Specify hash algorithm\n  -k, --keepsqlite      Retain Brunnhilde-generated sqlite db after processing\n  -l, --largefiles      Enable virus scanning of large files\n  -n, --noclam          Skip ClamAV virus scan\n  -r, --removefiles     Delete 'carved_files' directory when done (disk image\n                        input only)\n  -t, --throttle        Pause for 1s between Siegfried scans\n  -v, --verbosesf       Log verbose Siegfried output to terminal while\n                        processing\n  -V, --version         Display Brunnhilde version\n  -w, --warnings, --showwarnings\n                        Add Siegfried warnings to HTML report\n  -z, --scanarchives    Decompress and scan zip, tar, gzip, warc, arc with\n                        Siegfried\n  --save_assets SAVE_ASSETS\n                        DEPRECATED. Non-functional in Brunnhilde 1.9.1+ but\n                        retained for API stability\n  --load_assets LOAD_ASSETS\n                        DEPRECATED. Non-functional in Brunnhilde 1.9.1+ but\n                        retained for API stability\n  --csv CSV             Path to Siegfried CSV file to read as input\n                        (directories only)\n  --stdin               Read Siegfried CSV from piped stdin (directories only)\n  -o, --overwrite       Overwrite reports directory if it already exists\n  --in-memory-db        Use in-memory sqlite database rather than writing it\n                        to disk\n```  \n  \nFor file paths containing spaces in directory names, enclose the entire path in single or double quotes or make sure spaces are escaped properly (e.g. `CCA\\ Finding\\ Aid\\ Demo\\`).  \n\nBrunnhilde will accept absolute or relative paths for source and destination.  \n\nExample commands:\n\n#### Brunnhilde 1.9+\n\nBrunnhilde 1.9.0 introduces a simpler CLI syntax:\n\n`brunnhilde.py /directory/to/scan /output/directory/to/create`\n\nOr with options:\n\n`brunnhilde.py -ndz /home/user/diskimage.dd output_directory` - *scan a disk image (-d), skip the clamav virus check (-n), and instruct Siegfried to scan the contents of zip, tar, gzip, warc, and arc archive files (-z)*\n\n`sf -csv . | brunnhilde.py --stdin . output_directory` - *read a Siegfried CSV report of current directory from piped stdin*\n\n`brunnhilde.py --csv /path/to/existing/siegfried.csv source_directory output_directory` - *read a Siegfried CSV report of source_directory from a file*\n\nThe old way of calling Brunnhilde is officially deprecated but will continue to be supported for API stability:\n\n#### Brunnhilde 1.8 and below\n\n`brunnhilde.py /path/to/directory/to/scan /path/to/outputs/directory name_of_output_dir`\n\nSome examples:\n\n`brunnhilde.py -z \"/home/bcadmin/Desktop/Folder to Scan\" /home/bcadmin/Desktop brunnhilde-test-0` - *results in a new directory \"brunnhilde-test-0\" on the BitCurator desktop containing various reports on input source \"Folder to Scan\".* \n\n`brunnhilde.py -nz . /Users/twalsh/Desktop/ARCH123456` - *results in new directory \"ARCH123456\" on Mac desktop containing various reports on current working directory (-n skips ClamAV virus scan).*\n\n### SQLite database\n\nBy default, Brunnhilde will write a sqlite database to the output directory. To instead have Brunnhilde create and use an in-memory database in RAM, pass `--in-memory-db`.\n\n### Virus scanning\n\nBy default, Brunnhilde will use ClamAV to scan the contents of a directory or files in a disk image. Findings are written to a log and to the terminal. If any threats are found, Brunnhilde will print a warning to the terminal and direct the user to the ClamAV log file.  \n\nBy default, the maximum filesize and scansize for ClamAV are limited. To enable scanning of large files and large numbers of files, pass `--largefiles` as an argument. This will enable scans of unlimited size and scanning of files up to 4GB (files larger than 4GB are not supported by clamscan).\n\nTo disable virus scanning, pass `-n` or `--noclam` as an argument. Virus scanning is skipped in Windows regardless of the options passed to Brunnhilde.\n\n### Siegfried options  \n\nBy default, Brunnhilde uses the following Siegfried command:  \n\n```  \nsf -csv -hash md5 DIR \u003e CSV  \n```  \n\nTo enable scanning of archive files (zip, tar, gzip, warc, arc), pass `-z` or `--scanarchives` as an argument.  \n\nTo force Siegfried to pause for 1 second between file scans, pass `-t` or `--throttle` as an argument. \n\nTo force Siegfried to log verbose output to the terminal while processing, pass `-v` or `--verbosesf` as an argument.\n\nIn Brunnhilde 1.9+, you can pass Brunnhilde a Siegfried CSV file via piped stdin with the `--stdin` flag or by providing the path to a Siegfried CSV file with `--csv CSV`. The `--stdin` and `--csv CSV` options are limited to directory sources and do not work with disk images. When using these options, make sure that the `source` argument passed to Brunnhilde matches the directory scanned by Siegfried. Otherwise some options (e.g. virus scanning, running bulk_extractor) and statistics (e.g. total size) will not work as expected.\n\n### Specifying hash type  \n\nBrunnhilde uses the md5 hash algorithm by default. Other options are sha1, sha256, sha512, or none.  \n\nTo change the type of hash used, pass `--hash HASH` as an argument to Brunnhilde, replacing HASH with your choice of sha1, sha256, or sha512.\n\nIf the user specifies not to calculate checksums with `--hash none`, the resulting CSV outputs and HTML report will not contain information calculated from hash values, namely information about duplicate files in the source.\n\n### Report completeness  \n\nIn order to to keep the HTML from being excessively large, Brunnhilde does not include Siegfried warnings in the HTML report by default (the CSV is still created).  \n\nTo include Siegfried warnings in the report, pass `-w` or `--showwarnings` as an argument.\n\n### bulk_extractor  \n\nTo enable scanning of files with bulk_extractor, pass `-b` or `--bulkextractor` as arguments. This is disabled by default. Results are written to a 'bulk_extractor' sub-directory. In addition, running bulk_extractor adds a Social Security Number (SSN) section to the HTML report.\n\nIn Brunnhilde 1.9+, it is possible to instruct bulk_extractor to search for user-supplied patterns. Use the `--regex` flag to supply the path a file containing newline-separated regular expressions: `--regex /path/to/regex_file.txt`.\n\nSpecify the ssn_mode passed to bulk_extractor with `--ssn_mode INT`. Valid choices are 0, 1, or 2. If not specified, Brunnhilde will default to 1. See the following explanation of the modes from the [bulkextractor 1.5 release notes](https://github.com/simsong/bulk_extractor/blob/master/doc/announce/announce_1.5.md):\n\n```\nSSN recognition: you are now able to specify one of three SSN recognition modes:  \n\n-S ssn_mode=0 SSN’s must be labeled “SSN:”. Dashes or no dashes are okay.  \n-S ssn_mode=1 No “SSN” required, but dashes are required.  \n-S ssn_mode=2 No dashes required. Allow any 9-digit number that matches SSN allocation range.  \n```\n\n### Using disk images as input  \n\nIn `-d` mode, Brunnhilde uses SleuthKit's tsk_recover to export files from a disk image into a \"carved files\" directory for analysis. This works with raw images by default. In BitCurator or any other environment where libewf has been compiled into SleuthKit, Brunnhilde's -d mode also supports forensic disk image formats, including aff and ewf (E01). Due to the limitations of SleuthKit, Brunnhilde does not yet support characterizing disks that use the UDF filesystem.  \n\n**Note: tsk_recover does not retain file system dates, so the date reporting functionality of Brunnhilde is limited for non-HFS disk images. It is advised to create DFXML or similar files to retain/analyze file system metadata such as date stamps. In Brunnhilde 1.6.0+, a fiwalk-generated DFXML file is created for all non-HFS disk images.**\n\nBy default, Brunnhilde will keep a copy of the files exported from disk images in a \"carved_files\" directory. If you do not wish to keep a copy of these files after reporting is finished, you can pass the `-r` or `--removefiles` flags as arguments to Brunnhilde, which will cause it to delete the \"carved_files\" directory once all other tasks have finished.\n\nBrunnhilde also includes some options for more granular control of tsk_recover:\n\n`-a`: Export only allocated files (by default, Brunnhilde passes the -e option to tsk_recover, instructing it to extract all files from disk images, including deleted files, for reporting)  \n`--tsk_fstype`: Specify file system type in image (if not specified, tsk_recover will make best guess; to see possible values, type `tsk_recover -f list` in a terminal)  \n`--tsk_imgtype`: Specify disk image type (if not specified, tsk_recover will make best guess; to see possible values, type `tsk_recover -i list` in a terminal)  \n`--tsk_sector_offset`: Specify which volume on a disk to extract files from based on sector offset (see tsk_recover man page for more details)  \n\nAn example command for these values might be:  \n`brunnhilde.py -d --tsk_fstype fat --tsk_imgtype ewf --tsk_sector_offset 59 sampleimage.E01 . test`\n\nDisk image mode is not supported in Windows.\n\n### HFS-formatted disk images  \n\n*There is a known bug in older versions of unhfs, the command-line version of HFSExplorer, that prevented some files from being extracted from HFS disks. Be sure that you have the [bugfix release](https://sourceforge.net/projects/catacombae/files/HFSExplorer/0.23.1%20%28snapshot%202016-09-02%29/) of HFSExplorer installed. Versions of BitCurator since 1.7.106 are fine.*\n\nTo characterize HFS formatted disks in Brunnhilde, pass both the `-d` and `--hfs` flags as arguments, and be sure to use a raw disk image as the source (HFSExplorer is unable to process forensically packaged disk images). This functionality works \"off the shelf\" in BitCurator. Non-BitCurator environments will require you to install additional [dependencies](https://github.com/tw4l/brunnhilde#dependencies).  \n\nTo extract AppleDouble resource forks from HFS-formatted disk images, pass the `--hfs_resforks` or `--resforks` flag in addition to `-d` and `--hfs`.\n\nTo instruct `unhfs`/HFS Explorer to extract files from a speciic partition rather than using its default autodetection, pass the partition number as an integer with the `--hfs_partition` flag, e.g. `--hfs_partition 1`.\n\nTo instruct `unhfs`/HFS Explorer to extract only a specific file or directory from the HFS file system, pass the POSIX path with the `hfs_fsroot` flag, e.g. `--hfs_fsroot /Users/tessa/backup/` or `--hfs_fsroot \"my backup.dmg\"`.\n\n### Dependencies\n\nAll dependencies are already installed in BitCurator 1.7.106+. See instructions below for installing dependencies if you wish to use Brunnhilde in a different environment (Linux, Mac, or Windows).\n\n#### Internet connection (Brunnhilde 1.8 and below only)\n\nIn Brunnhilde 1.9+, an internet connection is no longer required.\n\nBrunnhilde 1.8 and below requires an internet connection to download the HTML report's Bootstrap JavaScript and CSS dependencies. If you are using Brunnhilde 1.8 or below in an environment without an internet connection, you can manually copy the `assets` directory from the Brunnhilde source repo into a directory named `brunnhilde` in your user's home directory, or use the `--load_assets PATH` flag to specify an alternate path to a Brunnhilde `assets` directory to use.\n\nIn Brunnhilde 1.9, the HTML report no longer uses Bootstrap and so does not need to download or cache JavaScript and CSS files.\n\n#### Core requirements (all operating systems)  \n\nFor Brunnhilde to report on any directory of content, the following must be installed in addition to Brunnhilde:\n\n* Python (2.7 or 3.4+; Python 3 is recommended)\n* [Siegfried](http://www.itforarchivists.com/siegfried): Brunnhilde is now compatible with all version of Siegfried, including 1.6+. It does not support MIME-Info or FDD signatures: for Brunnhilde to work, Siegfried must be using the PRONOM signature file only. If you have been using MIME-Info or FDD signatures as a replacement for or alongside PRONOM with Siegfried 1.5/1.6 on your machine, entering `roy build -multi 0` in the terminal should return you to Siegfried's default PRONOM-only identification mode and allow Brunnhilde to work properly.  \n\n#### Additional dependencies (for full functionality in Linux and macOS)\n\nFunctions such as reporting on the contents of disk images, scanning for personally identifiable information (PII), and virus scanning introduce additional dependencies.\n\n* [SleuthKit](http://www.sleuthkit.org/): Carves files from and creates DFXML reports for disk images containing FAT, NTSF, HFS+, EXT2/3, ISO9660, UFS, RAW, SWAP, and YAFFS2 file systems. Note: SleuthKit works only with raw disk images by default, and has additional dependencies such as [libewf](https://github.com/libyal/libewf) and [afflib](https://github.com/sshock/AFFLIBv3) that may or may not be installed depending on installation method for working with forensically-packaged disk images.  \n* [HFSExplorer](http://www.catacombae.org/hfsexplorer/): Carves files from disk images containing HFS file system  \n* [bulk_extractor](https://github.com/simsong/bulk_extractor): Scans for PII  \n* [ClamAV](https://www.clamav.net): Scans for viruses  \n* [tree](https://linux.die.net/man/1/tree): Reports on directory structure\n\n#### Linux  \n\n*Note: Assumes Debian-based distro. If other, use appropriate package manager or build from source.*  \n\n* HFSExplorer: Download bin files from [bugfix snapshot](https://sourceforge.net/projects/catacombae/files/HFSExplorer/0.23.1%20%28snapshot%202016-09-02%29/) and move to /usr/share/hfsexplorer.  \n* bulk_extractor: Build from source distribution using instructions found [here](https://github.com/simsong/bulk_extractor).  \n* Other dependencies:  \n```\n# sleuthkit \ngit clone git://github.com/sleuthkit/sleuthkit.git\ncd sleuthkit\n./bootstrap\n./configure\nmake\nsudo make install\nsudo ldconfig\n\n# clamav\nsudo apt-get install clamav\nsudo freshclam\n\n# tree\nsudo apt-get install tree\n```  \n\n#### macOS\n\n*Note: If not already installed on your system, first install [Homebrew](https://brew.sh/).*\n\n* HFSExplorer: Download bin files from [bugfix snapshot](https://sourceforge.net/projects/catacombae/files/HFSExplorer/0.23.1%20%28snapshot%202016-09-02%29/), unzip, rename directory to 'hfsexplorer' and move to /usr/local/share.  \n* Other dependencies:  \n```\nbrew install sleuthkit\nbrew install bulk_extractor\nbrew install clamav\nbrew install tree\n```\n\n#### Windows\n\n*Note: Windows support for Brunnhilde is limited. Normal reporting of directories should work without issue. Scanning of disk images, virus scanning, generating tree reports, and running bulk_extractor are not currently supported in Windows.*\n\n### Creators\n\n* Canadian Centre for Architecture\n* Tessa Walsh\n\nThis project was initially developed in 2016-2017 for the [Canadian Centre for Architecture](https://www.cca.qc.ca) by Tessa Walsh, Digital Archivist, as part of the development of the Archaeology of the Digital project.\n\n### Thanks\n\nThank you to Richard Lehane for writing Siegfried, Ross Spencer for ideas and help, Kevin Powell for suggesting the additions of ClamAV and bulk_extractor and writing the initial code to integrate these tools, Brian Dietz for suggesting improvements in tsk_recover and macOS functionality, and to the PRONOM team at the UK National Archives for building and maintaining such a wonderful tool.  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftw4l%2Fbrunnhilde","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftw4l%2Fbrunnhilde","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftw4l%2Fbrunnhilde/lists"}