{"id":21459198,"url":"https://github.com/citp/no-boundaries","last_synced_at":"2025-07-22T20:06:18.611Z","repository":{"id":80086676,"uuid":"279433334","full_name":"citp/no-boundaries","owner":"citp","description":null,"archived":false,"fork":false,"pushed_at":"2020-10-03T08:48:45.000Z","size":44579,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-17T04:21:56.069Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/citp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-13T23:30:22.000Z","updated_at":"2024-04-15T01:35:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"623f8dfe-02de-4c21-b835-dc149419de21","html_url":"https://github.com/citp/no-boundaries","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/citp/no-boundaries","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citp%2Fno-boundaries","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citp%2Fno-boundaries/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citp%2Fno-boundaries/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citp%2Fno-boundaries/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/citp","download_url":"https://codeload.github.com/citp/no-boundaries/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citp%2Fno-boundaries/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266563915,"owners_count":23948689,"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-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"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":[],"created_at":"2024-11-23T06:27:23.850Z","updated_at":"2025-07-22T20:06:18.600Z","avatar_url":"https://github.com/citp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"OpenWPM - No boundaries fork\n=======\nThis is a fork of OpenWPM used in the \"[No boundaries: data exfiltration by third parties embedded on web pages](https://webtransparency.cs.princeton.edu/no_boundaries/)\" study, which appeared at 2020 Privacy Enhancing Technologies Symposium.\n\nPlease check the [upstream repository of OpenWPM](https://github.com/mozilla/OpenWPM/) for the latest README and instructions. The instructions below are for an (now) outdated version of OpenWPM that we used in our study.\n\n### Scripts and data files specific to this study:\n- **measurement_passive_identity.py**: Used to detect Login Manager misuse and Whole-DOM Scraping\n- **measurement_dom_chunk.py**: Used to detect Whole-DOM Scraping\n- **measurement_dom_chunk_no_injection.py** Used to detect Whole-DOM Scraping\n- **measurement_facebook_api.py**: Used to detect Social API misuse\n- **sites_to_crawl.json**: The list of homepage and inner page URLs crawled in the study\n\n\nOpenWPM is a web privacy measurement framework which makes it easy to collect\ndata for privacy studies on a scale of thousands to millions of site. OpenWPM\nis built on top of Firefox, with automation provided by Selenium. It includes\nseveral hooks for data collection, including a proxy, a Firefox extension, and\naccess to Flash cookies. Check out the instrumentation section below for more\ndetails.\n\nInstallation\n------------\n\nOpenWPM has been developed and tested on Ubuntu 14.04/16.04. An installation\nscript, `install.sh` is included to install both the system and python\ndependencies automatically. A few of the python dependencies require specific\nversions, so you should install the dependencies in a virtual environment if\nyou're installing a shared machine. If you plan to develop OpenWPM's\ninstrumentation extension or run tests you will also need to install the\ndevelopment dependencies included in `install-dev.sh`.\n\nIt is likely that OpenWPM will work on platforms other than Ubuntu, however\nwe do not officially support anything else. For pointers on alternative\nplatform support see\n[the wiki](https://github.com/citp/OpenWPM/wiki/OpenWPM-on-Alternate-Platforms).\n\nQuick Start\n-----------\n\nOnce installed, it is very easy to run a quick test of OpenWPM. Check out\n`demo.py` for an example. This will use the default setting specified in\n`automation/default_manager_params.json` and\n`automation/default_browser_params.json`, with the exception of the changes\nspecified in `demo.py`.\n\nMore information on the instrumentation and configuration parameters is given\nbelow.\n\n\nThe [wiki](https://github.com/citp/OpenWPM/wiki) provides a more in-depth\ntutorial, including a\n[platform demo](https://github.com/citp/OpenWPM/wiki/Platform-Demo)\nand a description of the\n[additional commands](https://github.com/citp/OpenWPM/wiki/Available-Commands)\navailable. You can also take a look at two of our past studies, which use the\ninfrastructure:\n\n1. [The Web Never Forgets](https://github.com/citp/TheWebNeverForgets)\n2. [Cookies that Give You Away](https://github.com/englehardt/cookies-that-give-you-away)\n\nInstrumentation and Data Access\n-------------------------------\n\nOpenWPM provides several instrumentation modules which can be enabled\nindependently of each other for each crawl. With the exception of Javascript\nresponse body content, all instrumentation saves to a SQLite database specified\nby `manager_params['database_name']` in the main output directory. Javascript\nbodies are saved to `javascript.ldb`. The SQLite schema specified by:\n`automation/schema.sql`, instrumentation may specify additional tables necessary\nfor their measurement data (see\n[extension tables](https://github.com/citp/OpenWPM/tree/master/automation/Extension/firefox/data)).\n\n* HTTP Request and Response Headers, POST request bodies\n    * Set `browser_params['http_instrument'] = True`\n    * Data is saved to the `http_requests` and `http_responses` tables.\n    * OCSP POST request bodies are not recorded\n    * Note: request and response headers for cached content are also saved,\n        with the exception of images.\n        See: [Bug 634073](https://bugzilla.mozilla.org/show_bug.cgi?id=634073).\n* Javascript Calls\n    * Records all method calls (with arguments) and property accesses for APIs\n      of potential fingerprinting interest:\n        * HTML5 Canvas\n        * HTML5 WebRTC\n        * HTML5 Audio\n        * Plugin access (via `navigator.plugins`)\n        * MIMEType access (via `navigator.mimeTypes`)\n        * `window.Storage`, `window.localStorage`, `window.sessionStorage`,\n              and `window.name` access.\n        * Navigator properties (e.g. `appCodeName`, `oscpu`, `userAgent`, ...)\n        * Window properties (via `window.screen`)\n    * Set `browser_params['js_instrument'] = True`\n    * Data is saved to the `javascript` table.\n* Javascript Files\n    * Saves all Javascript files encountered during the crawl to a `LevelDB`\n        database de-duplicated by the md5 hash of the content.\n    * Set `browser_params['save_javascript'] = True`\n    * The `content_hash` column of the `http_responses` table contains the md5\n        hash for each script, and can be used to do content lookups in the\n        LevelDB content database.\n    * This instrumentation can be easily expanded to other content types.\n* Flash Cookies\n    * Recorded by scanning the respective Flash directories after each page visit.\n    * To enable: call the `CommandSequence::dump_flash_cookies` command after\n        a page visit. Note that calling this command will close the current tab\n        before recording the cookie changes.\n    * Data is saved to the `flash_cookies` table.\n    * NOTE: Flash cookies are shared across browsers, so this instrumentation\n        will not correctly attribute flash cookie changes if more than 1\n        browser is running on the machine.\n* Cookie Access (*Experimental* -- Needs tests)\n    * Set `browser_params['cookie_instrument'] = True`\n    * Data is saved to the `javascript_cookies` table.\n    * Will record cookies set both by Javascript and via HTTP Responses\n* Content Policy Calls (*Experimental* -- Needs tests)\n    * Set `browser_params['cp_instrument'] = True`\n    * Data is saved to the `content_policy` table.\n    * Provides additional information about what caused a request and what it's for\n    * NOTE: This instrumentation is largely unchanged since it was ported from\n        [FourthParty](https://github.com/fourthparty/fourthparty), and is not\n        linked to any other instrumentation tables.\n* Cookie Access (Alternate)\n    * Recorded by scanning the `cookies.sqlite` database in the Firefox profile\n        directory.\n    * Should contain both cookies added by Javascript and by HTTP Responses\n    * To enable: call the `CommandSequence::dump_profile_cookies` command after\n        a page visit. Note that calling this command will close the current tab\n        before recording the cookie changes.\n    * Data is saved to the `profile_cookies` table\n* Log Files\n    * Stored in the directory specified by `manager_params['data_directory']`.\n    * Name specified by `manager_params['log_file']`.\n* Browser Profile\n    * Contains cookies, Flash objects, and so on that are dumped after a crawl\n        is finished\n    * Automatically saved when the platform closes or crashes by specifying\n        `browser_params['profile_archive_dir']`.\n    * Save on-demand with the `CommandSequence::dump_profile` command.\n* **DEPRECATED** HTTP Request and Response Headers via mitmproxy\n    * This will be removed in future releases\n    * Set `browser_params['proxy'] = True`\n    * Data is saved to the `http_requests_proxy` and `http_responses_proxy`\n        tables.\n    * Saves both HTTP and HTTPS request and response headers\n    * Several drawbacks:\n        * Cached requests and responses are missed entirely (See #71)\n        * Some HTTPS connections fail with certificate warnings (See #53)\n        * The mitmproxy version used (v0.13) is a few releases behind the\n            current mitmproxy library and will likely continue to have more\n            issues unless updated.\n        * Has significantly less context available around a request/response\n            than is available from within the browser.\n* **DEPRECATED** Javascript Response Bodies via mitmproxy\n    * This will be removed in future releases\n    * Set `browser_params['save_javascript_proxy'] = True`\n    * Saves javascript response bodies to a LevelDB database de-duplicated by\n        the murmurhash3 of the content. `content_hash` in `http_response_proxy`\n        keys into this content database.\n    * NOTE: In addition to the other drawbacks of proxy-based measurements,\n        content must be decoded before saving and not all current encodings are\n        supported. In particular, brotli (`br`) is not supported.\n* **DEPRECATED** HTTP Request and Response Cookies via mitmproxy\n    * This will be removed in future releases\n    * Derived post-crawl from proxy-based HTTP instrumentation\n    * To enable: call\n      `python automation/utilities/build_cookie_table.py \u003csqlite_database\u003e`.\n    * Data is saved to the `http_request_cookies_proxy` and\n        `http_response_cookies_proxy` tables.\n    * Several drawbacks:\n        * Will not detect cookies set via Javascript, but will still record\n            when those cookies are sent with requests.\n        * Cookie parsing is done using a custom `Cookie.py` module. Although a\n            significant effort went into replicating Firefox's cookie parsing,\n            it may not be a faithful reproduction.\n\nBrowser and Platform Configuration\n----------------------------------\n\nThe browser and platform can be configured by two separate dictionaries. The\nplatform configuration options can be set in `manager_params`, while the\nbrowser configuration options can be set in `browser_params`. The default\nsettings are given in `automation/default_manager_params.json` and\n`automation/default_browser_params.json`.\n\nTo load the default configuration parameter dictionaries we provide a helper\nfunction `TaskManager::load_default_params`. For example:\n\n```python\nfrom automation import TaskManager\nmanager_params, browser_params = TaskManager.load_default_params(num_browsers=5)\n```\n\nwhere `manager_params` is a dictionary and `browser_params` is a length 5 list\nof configuration dictionaries.\n\n### Platform Configuration Options\n\n* `data_directory`\n  * The directory in which to output the crawl database and related files. The\n    directory given will be created if it does not exist.\n* `log_directory`\n  * The directory in which to output platform logs. The\n    directory given will be created if it does not exist.\n* `log_file`\n  * The name of the log file to be written to `log_directory`.\n* `database_name`\n  * The name of the database file to be written to `data_directory`\n* `failure_limit`\n  * The number of successive command failures the platform will tolerate before\n    raising a `CommandExecutionError` exception. Otherwise the default is set\n    to 2 x the number of browsers plus 10.\n* `testing`\n  * A platform wide flag that can be used to only run certain functionality\n    while testing. For example, the Javascript instrumentation\n    [exposes its instrumentation function](https://github.com/citp/OpenWPM/blob/91751831647c37b769f0039d99d0a164384c76ae/automation/Extension/firefox/data/content.js#L447-L449)\n    on the page script global to allow test scripts to instrument objects\n    on-the-fly. Depending on where you would like to add test functionality,\n    you may need to propagate the flag.\n  * This is not something you should enable during normal crawls.\n\n### Browser Configuration Options\n\nNote: Instrumentation configuration options are described in the\n*Instrumentation and Data Access* section and profile configuration options are\ndescribed in the *Browser Profile Support* section. As such, these options are\nleft out of this section.\n\n* `disable_webdriver_self_id`\n  * Prevents Selenium from identifying itself in the DOM. See\n    [Issue #91](https://github.com/citp/OpenWPM/issues/91).\n* `bot_mitigation`\n  * Performs some actions to prevent the platform from being detected as a bot.\n  * Note, these aren't comprehensive and automated interaction with the site\n    will still appear very bot-like.\n* `disable_flash`\n  * Flash is disabled by default. Set this to `False` to re-enable. Note that\n    flash cookies are shared between browsers.\n* `headless`\n  * Launch the browser in a virtual frame buffer, no GUI will be visible.\n  * Use this when running browsers on a remote machine or to run crawls in the\n      background on a local machine.\n* `browser`\n  * Used to specify which browser to launch. Currently only `firefox` is\n    supported.\n  * Other browsers may be added in the future.\n* `tp_cookies`\n  * Specifies the third-party cookie policy to set in Firefox.\n  * The following options are supported:\n    * `always`: Accept all third-party cookies\n    * `never`: Never accept any third-party cookies\n    * `from_visited`: Only accept third-party cookies from sites that have been\n      visited as a first party.\n* `donottrack`\n  * Set to `True` to enable Do Not Track in the browser.\n* `ghostery`\n  * Set to `True` to enable Ghostery with all blocking enabled\n  * NOTE: The Ghostery version used (including filter lists) may be outdated.\n    It's recommended that you update the xpi and `store.json` file (included in\n    the extension profile directory). These can be placed\n    [here](https://github.com/citp/OpenWPM/tree/master/automation/DeployBrowsers/firefox_extensions/ghostery)\n* `https-everywhere`\n  * Set to `True` to enable HTTPS Everywhere in the browser.\n  * NOTE: The HTTPS Everywhere version may be outdated. It's recommended you\n    update the xpi\n    [located here](https://github.com/citp/OpenWPM/tree/master/automation/DeployBrowsers/firefox_extensions)\n    before crawling.\n* `adblock-plus`\n  * Set to `True` to enable AdBlock Plus in the browser.\n  * The filter lists should be automatically downloaded and installed, but the\n    xpi, [located here](https://github.com/citp/OpenWPM/tree/master/automation/DeployBrowsers/firefox_extensions)\n    , might be outdated.\n  * NOTE: There is a known issue of AdBlock Plus not blocking all resources\n    on the first page visit. See\n    [Issue #35](https://github.com/citp/OpenWPM/issues/35)\n    for more information.\n* **NOT SUPPORTED** ` tracking-protection`\n  * Set to `True` to enable Firefox's built-in\n    [Tracking Protection](https://developer.mozilla.org/en-US/Firefox/Privacy/Tracking_Protection).\n  * NOTE: This is not currently supported. See\n    [Issue #101](https://github.com/citp/OpenWPM/issues/101) for more\n    information.\n\nBrowser Profile Support\n-----------------------\n\n### Stateful vs Stateless crawls\n\nBy default OpenWPM performs a \"stateful\" crawl, in that it keeps a consistent\nbrowser profile between page visits in the same browser. If the browser\nfreezes or crashes during the crawl, the profile is saved to disk and restored\nbefore the next page visit.\n\nIt's also possible to run \"stateless\" crawls, in which each new page visit uses\na fresh browser profile. To perform a stateless crawl you can restart the\nbrowser after each command sequence by setting the `reset` initialization\nargument to `True` when creating the command sequence. As an example:\n\n```python\nmanager = TaskManager.TaskManager(manager_params, browser_params)\n\nfor site in sites:\n    command_sequence = CommandSequence.CommandSequence(site, reset=True)\n    command_sequence.get(sleep=30, timeout=60)\n    command_sequence.dump_profile_cookies(120)\n    manager.execute_command_sequence(command_sequence)\n```\n\nIn this example, the browser will `get` the requested `site`, sleep for 30\nseconds, dump the profile cookies to the crawl database, and then restart the\nbrowser before visiting the next `site` in `sites`.\n\n### Loading and saving a browser profile\n\nIt's possible to load and save profiles during stateful crawls. Profile dumps\ncurrently consist of the following browser storage items:\n\n* cookies\n* localStorage\n* IndexedDB\n* browser history\n\nOther browser state, such as the browser cache, is not saved. In\n[Issue #62](https://github.com/citp/OpenWPM/issues/62) we plan to expand\nprofiles to include all browser storage.\n\n#### Save a profile\n\nA browser's profile can be saved to disk for use in later crawls. This can be\ndone using a browser command or by setting a browser configuration parameter.\nFor long running crawls we recommend saving the profile using the browser\nconfiguration parameter as the platform will take steps to save the\nprofile in the event of a platform-level crash, whereas there is no guarantee\nthe browser command will run before a crash.\n\n**Browser configuration parameter:** Set the `profile_archive_dir` browser\nparameter to a directory where the browser profile should be saved. The profile\nwill be automatically saved when `TaskManager::close` is called or when a\nplatform-level crash occurs.\n\n**Browser command:** See the command definition\n[wiki page](https://github.com/citp/OpenWPM/wiki/Available-Commands#dump_profile)\nfor more information.\n\n#### Load a profile\n\nTo load a profile, specify the `profile_tar` browser parameter in the browser\nconfiguration dictionary. This should point to the location of the\n`profile.tar` or (`profile.tar.gz` if compressed) file produced by OpenWPM.\nThe profile will be automatically extracted and loaded into the browser\ninstance for which the configuration parameter was set.\n\nDevelopment pointers\n--------------------\n\nMuch of OpenWPM's instrumentation is included in a Firefox add-on SDK extension.\nThus, in order to add or change instrumentation you will need a few additional\ndependencies, which can be installed with `install-dev.sh`.\n\n### Editing instrumentation\n\nThe extension instrumentation is included in `/automation/Extension/firefox/`.\nAny edits within this directory will require the extension to be re-built with\n`jpm` to produce a new `openwpm.xpi` with your updates. For more information on\ndeveloping a Firefox extension, we recommend reading this\n[MDN introductory tutorial](https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Getting_Started_(jpm)),\n as well as the [jpm reference page](https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm).\n\n### Debugging the platform\n\nManual debugging with OpenWPM can be difficult. By design the platform runs all\nbrowsers in separate processes and swallows all exceptions (with the intent of\ncontinuing the crawl). We recommend using\n[manual_test.py](https://github.com/citp/OpenWPM/blob/master/test/manual_test.py).\n\nThis utility allows manual debugging of the extension instrumentation with or\nwithout Selenium enabled, as well as makes it easy to launch a Selenium\ninstance (without any instrumentation)\n* `python manual_test.py` uses `jpm` to build the current extension directory\n  and launch a Firefox instance with it.\n* `python manual_test.py --selenium` launches a Firefox Selenium instance\n  after using `jpm` to automatically rebuild `openwpm.xpi`. The script then\n  drops into an `ipython` shell where the webdriver instance is available\n  through variable `driver`.\n* `python manual_test.py --selenium --no_extension` launches a Firefox Selenium\n  instance with no instrumentation. The script then\n  drops into an `ipython` shell where the webdriver instance is available\n  through variable `driver`.\n\n\n### Running tests\n\nOpenWPM's tests are build on `py.test`. To run the tests you will need a few\nadditional dependencies, which can be installed by running `install-dev.sh`.\n\nOnce installed, execute `py.test -vv` in the test directory to run all tests.\n\n\nTroubleshooting\n---------------\n\n1. `IOError: [Errno 2] No such file or directory: '../../firefox-bin/application.ini'`\n\n  This error occurs when the platform can't find a standalone Firefox binary in\n  the root directory of OpenWPM. The `install.sh` script will download and unzip\n  the appropriate version of Firefox for you. If you've run this script but still\n  don't have the binary installed note that the script will exit if any command\n  fails, so re-run the install script checking that no command fails.\n\n2. `WebDriverException: Message: The browser appears to have exited before we could connect...`\n\n  This error indicates that Firefox exited during startup (or was prevented from\n  starting). There are many possible causes of this error:\n\n  * If you are seeing this error for all browser spawn attempts check that:\n    * Both selenium and Firefox are the appropriate versions. Run the following\n      commands and check that the versions output match the required versions in\n      `install.sh` and `requirements.txt`. If not, re-run the install script.\n      ```sh\n      cd firefox-bin/\n      firefox --version\n      ```\n\n      and\n\n      ```sh\n        pip show selenium\n      ```\n    * If you are running in a headless environment (e.g. a remote server), ensure\n      that all browsers have the `headless` browser parameter set to `True` before\n      launching.\n  * If you are seeing this error randomly during crawls it can be caused by\n    an overtaxed system, either memory or CPU usage. Try lowering the number of\n    concurrent browsers.\n\n\nDisclaimer\n-----------\n\nNote that OpenWPM is under active development, and should be considered\nexperimental software. The repository may contain experimental features that\naren't fully tested. We recommend using a [tagged\nrelease](https://github.com/citp/OpenWPM/releases).\n\nAlthough OpenWPM is actively used by our group for research studies and we\nregularly use of the data collected, it is still possible there are unknown bugs\nin the infrastructure. We are in the process of writing comprehensive tests to\nverify the integrity of all included instrumentation. Prior to using OpenWPM\nfor your own research we encourage you to write tests (and submit pull\nrequests!) for any instrumentation that isn't currently included in our test\nscripts.\n\nCitation\n--------\n\nIf you use OpenWPM in your research, please cite our CCS 2016 [publication](http://randomwalker.info/publications/OpenWPM_1_million_site_tracking_measurement.pdf)\non the infrastructure. You can use the following BibTeX.\n\n    @inproceedings{englehardt2016census,\n        author    = \"Steven Englehardt and Arvind Narayanan\",\n        title     = \"{Online tracking: A 1-million-site measurement and analysis}\",\n        booktitle = {Proceedings of ACM CCS 2016},\n        year      = \"2016\",\n    }\n\nAs of May 2017 OpenWPM has been used in [14 studies](https://webtransparency.cs.princeton.edu/webcensus/index.html#Users).\n\nLicense\n-------\n\nOpenWPM is licensed under GNU GPLv3. Additional code has been included from\n[FourthParty](https://github.com/fourthparty/fourthparty) and\n[Privacy Badger](https://github.com/EFForg/privacybadgerfirefox), both of which\nare licensed GPLv3+.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcitp%2Fno-boundaries","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcitp%2Fno-boundaries","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcitp%2Fno-boundaries/lists"}