{"id":107465,"date":"2025-08-11T11:00:00","date_gmt":"2025-08-11T11:00:00","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=107465"},"modified":"2025-08-06T07:18:11","modified_gmt":"2025-08-06T07:18:11","slug":"power-bi-tmdl-benefits-security-risks-best-practices","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/business-intelligence\/power-bi-tmdl-benefits-security-risks-best-practices\/","title":{"rendered":"Power BI TMDL View: Benefits, Security Risks &amp; Best Practices"},"content":{"rendered":"\n<p>The <a href=\"https:\/\/learn.microsoft.com\/en-us\/analysis-services\/tmdl\/tmdl-overview?view=sql-analysis-services-2025\" target=\"_blank\" rel=\"noreferrer noopener\">Tabular Model Definition Language (TMDL)<\/a> provides a simpler way of defining <a href=\"https:\/\/learn.microsoft.com\/en-us\/power-bi\/connect-data\/service-datasets-understand\" target=\"_blank\" rel=\"noreferrer noopener\">Power BI Semantic Models<\/a>. Unlike the JSON-based <a href=\"https:\/\/learn.microsoft.com\/en-us\/analysis-services\/tmsl\/tabular-model-scripting-language-tmsl-reference?view=sql-analysis-services-2025\" target=\"_blank\" rel=\"noreferrer noopener\">Tabular Model Scripting Language (TMSL)<\/a>, TMDL uses a more accessible tab-based format for specifying <a href=\"https:\/\/learn.microsoft.com\/en-us\/power-bi\/transform-model\/desktop-measures\" target=\"_blank\" rel=\"noreferrer noopener\">DAX measures<\/a>, relationships, and <a href=\"https:\/\/learn.microsoft.com\/en-us\/power-query\/power-query-what-is-power-query\" target=\"_blank\" rel=\"noreferrer noopener\">Power Query<\/a> code.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"655\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-36-1024x655.png\" alt=\"Example of TMDL format\" class=\"wp-image-107466\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-36-1024x655.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-36-300x192.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-36-768x492.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-36.png 1125w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 1 &#8211; Example of TMDL format<\/em><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-benefits-of-using-tmdl-view\">Benefits of Using TMDL View<\/h2>\n\n\n\n<p>In January 2025, Microsoft introduced the <a href=\"https:\/\/powerbi.microsoft.com\/en-us\/blog\/power-bi-january-2025-feature-summary\/\" target=\"_blank\" rel=\"noreferrer noopener\">TMDL View<\/a>, which makes it easier for pro-code developers who use conventional programming languages with semantic models to share and reuse TMDL. With the click of the \u201cApply\u201d button (see Figure 2), you can update the model. If you\u2019ve ever had to update a Power Query function across multiple semantic models or dataflows, you know how time-consuming it can be, so this is a powerful new feature by comparison.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"625\" height=\"567\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-37.png\" alt=\"Updating your model in TDLM view with just the click of the 'Apply' button\" class=\"wp-image-107467\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-37.png 625w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-37-300x272.png 300w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 2 &#8211; Updating your model in TDLM view with just the click of the &#8216;Apply&#8217; button<\/em><\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>This feature has led to the sharing of TMDL scripts on social media and the launch of sites like <a href=\"https:\/\/fabsnippets.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/fabsnippets.com<\/a> and the <a href=\"https:\/\/community.fabric.microsoft.com\/t5\/TMDL-Gallery\/bd-p\/pbi_tmdlgallery\">T<\/a><a href=\"https:\/\/community.fabric.microsoft.com\/t5\/TMDL-Gallery\/bd-p\/pbi_tmdlgallery\" target=\"_blank\" rel=\"noreferrer noopener\">MDL Gallery<\/a>, where users exchange code and best practices. It highlights how active and generous the Power BI community is.\u00a0 <\/p>\n\n\n\n<p>However, with the introduction of TMDL View, I would caution the community about bad actors who might take advantage of that generosity. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-security-risks-of-tmdl-scripts\">Security Risks of TMDL Scripts<\/h2>\n\n\n\n<p>If you plan to use a TMDL script from another website or individual, you should treat it as <strong>untrusted code<\/strong>. Untrusted code can lead to data leakage or trigger updates to your systems without your immediate knowledge.&nbsp;<\/p>\n\n\n\n<p>As of July 2025, I\u2019ve identified several risks associated with running a TMDL script in TMDL View that you should consider beforehand, along with mitigation techniques you can use to prevent any risk of a security breach.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-sql-injection-via-native-queries\">SQL Injection via Native Queries<\/h3>\n\n\n\n<p>If you are working with SQL-based sources, there is a chance you have disabled the \u201cRequire user approval for new native database queries\u201d setting (see Figure 3). This is a safety mechanism you may have turned off months ago, but when enabled, it prompts you with a message similar to the one shown in Figure 3.<\/p>\n\n\n\n<p>If you apply a TMDL script in Power BI Desktop, it could contain SQL code that you do not want to execute. You can consider this a potential form of <a href=\"https:\/\/owasp.org\/www-community\/attacks\/SQL_Injection\" target=\"_blank\" rel=\"noreferrer noopener\">SQL injection<\/a> within Power Query.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"879\" height=\"423\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-38.png\" alt=\"Screenshot of disabling user approval for native database queries\" class=\"wp-image-107468\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-38.png 879w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-38-300x144.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-38-768x370.png 768w\" sizes=\"auto, (max-width: 879px) 100vw, 879px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 3 &#8211; Screenshot of disabling user approval for native database queries<\/em><\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>This SQL injection can perform actions such as updating permissions, extracting sensitive data, or creating a user.\u00a0<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Mitigation Technique<\/h4>\n\n\n\n<p>Turn on <strong>\u201cRequire user approval for new native database queries\u201d<\/strong> before running the TMDL script in TMDL View. When this setting is enabled, you will see a message similar to Figure 4 before any native database queries are executed.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"766\" height=\"70\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-39.png\" alt=\"Example of security prompt in Power BI desktop, prompting if you want to run a native SQL script\" class=\"wp-image-107469\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-39.png 766w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-39-300x27.png 300w\" sizes=\"auto, (max-width: 766px) 100vw, 766px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 4 &#8211; Example of security prompt in Power BI desktop, prompting if you want to run a native SQL script<\/em><\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>You should also inspect the Power Query code for any database connection functions that include a Query argument, such as <a href=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/sql-database\" target=\"_blank\" rel=\"noreferrer noopener\">Sql.Database<\/a>, <a href=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/oracle-database\" target=\"_blank\" rel=\"noreferrer noopener\">Oracle.Database<\/a>, <a href=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/odbc-query\" target=\"_blank\" rel=\"noreferrer noopener\">Odbc.Query<\/a>, and <a href=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/postgresql-database\" target=\"_blank\" rel=\"noreferrer noopener\">PostgreSQL.Database<\/a>. The Query argument contains the script that will be executed against your database.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-python-and-r-execution-risks\">Python and R Execution Risks<\/h3>\n\n\n\n<p>You may not be aware that <a href=\"https:\/\/www.python.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Python<\/a> and <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/bi-sql-server\/text-mining-and-sentiment-analysis-with-r\/\" target=\"_blank\" rel=\"noreferrer noopener\">R<\/a> also depend on the <strong><a href=\"https:\/\/learn.microsoft.com\/en-us\/power-query\/native-database-query\" target=\"_blank\" rel=\"noreferrer noopener\">\u201cNative Database Queries\u201d<\/a><\/strong> setting. When this setting is enabled, it will prompt you to confirm whether you want to execute the code. However, I often see this setting disabled for the sake of \u2018psychological acceptability\u2019 &#8211; the principle that security warnings should match user expectations. Unfortunately, that expectation is often to avoid them entirely. If you\u2019re using Python or R in your Power BI Desktop files, you could accidentally allow code to execute that you did not intend. Python or R code can perform many actions on your machine and could even be used to extract information from your operating system that you may not want to allow (see example in Figure 5).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"707\" height=\"473\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-40.png\" alt=\"Example of Python code in Power Query\" class=\"wp-image-107470\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-40.png 707w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-40-300x201.png 300w\" sizes=\"auto, (max-width: 707px) 100vw, 707px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 5 &#8211; Example of Python code in Power Query<\/em><\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Mitigation Technique<\/h4>\n\n\n\n<p>Turn on <strong>\u201cRequire user approval for new native database queries\u201d<\/strong> before running the TMDL script in TMDL View and inspect the Power Query code for any use of R.Execute or Python.Execute.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-privacy-settings-and-data-leakage\">Privacy Settings and Data Leakage<\/h2>\n\n\n\n<p>If you see the term <strong>\u201cfastCombine\u201d<\/strong> under a model in a TMDL script (see Figure 6), you should inspect it carefully as it is shorthand for setting the model to <strong>&#8220;Always ignore Privacy Level Settings.&#8221;<\/strong> This setting disables privacy checks that normally protect data when combining sources from different locations. For example, it can be useful when combining data from a public website with internal data for analysis. However, it could also be used to pull data from an Excel file and send it to a web service without your knowledge.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"420\" height=\"192\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-41.png\" alt=\"Example of fastCombine in TMDL Script\" class=\"wp-image-107471\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-41.png 420w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-41-300x137.png 300w\" sizes=\"auto, (max-width: 420px) 100vw, 420px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 6 &#8211; Example of fastCombine in TMDL Script<\/em><\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Mitigation Technique<\/h4>\n\n\n\n<p>Remove <strong>fastCombine<\/strong> from the script and make sure the setting <strong>\u201cAlways combine data according to your Privacy Level settings for each source\u201d<\/strong> is enabled under Global &gt; Security &gt; Privacy Levels. With these settings turned on, you will be prompted when data sources are combined and can deny any combinations you find suspicious.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"253\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-42.png\" alt=\"Set Privacy levels to the most restrictive before running an untrusted TMDL script\" class=\"wp-image-107473\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-42.png 720w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-42-300x105.png 300w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 7 &#8211; Set Privacy levels to the most restrictive before running an untrusted TMDL script<\/em><\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-web-contents-and-external-data-transfers\">Web.Contents and External Data Transfers<\/h3>\n\n\n\n<p><a href=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/web-contents\" target=\"_blank\" rel=\"noreferrer noopener\">Web.Contents<\/a> is a powerful function that can access websites and application programming interfaces, but it can also send data outside your organization. For example, Figure 8 shows a TMDL script with a Web.Contents function that could upload data to an external endpoint. When Web.Contents uses the Content argument, it becomes a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Reference\/Methods\/POST\" target=\"_blank\" rel=\"noreferrer noopener\">POST request<\/a>, and you will be asked to connect via an anonymous connection the first time you make this connection on your machine.<\/p>\n\n\n\n<p>Once established, you will not be asked to set up that connection again unless you clear the permissions in &#8216;data source settings&#8217;. While you may be prompted to connect anonymously, be cautious of <a href=\"https:\/\/www.wix.com\/encyclopedia\/definition\/domain-spoofing\" target=\"_blank\" rel=\"noreferrer noopener\">domain spoofing<\/a>, where the URL is crafted to look like a legitimate site. For instance, powerbi.com is a legitimate Microsoft site, but powerb\u00ec.com (with an accented \u2018\u00ec\u2019) is not. You could be tricked into thinking you are connecting to a trusted site when in fact, you are sending data to a malicious one.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"943\" height=\"391\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-43.png\" alt=\"Example of Web.Contents performing a POST request\" class=\"wp-image-107474\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-43.png 943w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-43-300x124.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-43-768x318.png 768w\" sizes=\"auto, (max-width: 943px) 100vw, 943px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 8 &#8211; Example of Web.Contents performing a POST request<\/em><\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Mitigation Technique<\/h4>\n\n\n\n<p>Make sure the setting <strong>\u201cAlways combine data according to your Privacy Level settings for each source\u201d<\/strong> is enabled under Global &gt; Security &gt; Privacy Levels in Power BI Desktop. Inspect the TMDL script for the presence of Web.Contents and verify that it is performing legitimate data calls. If the Content parameter is used, scrutinize its use carefully, as anonymous connections sending data can be highly suspicious.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-folder-files-and-local-file-access\">Folder.Files and Local File Access<\/h2>\n\n\n\n<p><a href=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/folder-files\" target=\"_blank\" rel=\"noreferrer noopener\">Folder.Files<\/a> allows you to access file contents on your machine but can also be used to retrieve sensitive documents from your computer.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"183\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-44-1024x183.png\" alt=\"Example of Folder.Files accessing a C Drive if executed\" class=\"wp-image-107477\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-44-1024x183.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-44-300x54.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-44-768x137.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-44.png 1125w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 9 &#8211; Example of Folder.Files accessing a C Drive if executed<\/em><\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Mitigation Technique<\/h4>\n\n\n\n<p>Make sure the setting <strong>\u201cAlways combine data according to your Privacy Level settings for each source\u201d<\/strong> is enabled under Global &gt; Security &gt; Privacy Levels in Power BI Desktop. Inspect the TMDL script for the presence of Folder.Files and ensure it is performing legitimate data calls.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Considerations<\/h2>\n\n\n\n<p>If you\u2019re reading this and wondering how someone could miss those risks in a script, the answer lies in advances in obfuscation &#8211; the act of hiding a code\u2019s purpose by making it confusing or hard to read. <\/p>\n\n\n\n<p>Furthermore, with <a href=\"https:\/\/developers.google.com\/machine-learning\/resources\/intro-llms\" target=\"_blank\" rel=\"noreferrer noopener\">Large Language Models (LLM)<\/a> like <a href=\"https:\/\/openai.com\/chatgpt\/overview\/\" target=\"_blank\" rel=\"noreferrer noopener\">ChatGPT<\/a><sup>1<\/sup> , it has become quite simple to obfuscate code or bury it between other steps. For example, in Figure 10, I have highlighted a Web.Contents call hidden inside code that generates a Calendar\/Date dimension. In Figure 11, I simply asked an LLM model to hide the Python code that pulls files from a specific C drive. When a script is large or obfuscated, such code can easily be overlooked.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"602\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-45-1024x602.png\" alt=\"Example of Web.Contents placed between steps that build a Calendar\/Date dimension table\" class=\"wp-image-107478\" style=\"width:832px;height:auto\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-45-1024x602.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-45-300x176.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-45-768x451.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-45.png 1123w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 10 &#8211; Example of Web.Contents placed between steps that build a Calendar\/Date dimension table<\/em><\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"202\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-46-1024x202.png\" alt=\"Example of Python code obfuscated\" class=\"wp-image-107479\" style=\"width:832px;height:auto\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-46-1024x202.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-46-300x59.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-46-768x152.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/image-46.png 1125w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><em>Figure 11 &#8211; Example of Python code obfuscated<\/em><\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-hiding-malicious-code\">Hiding malicious code<\/h3>\n\n\n\n<p>It\u2019s never been easier to share Power BI scripts online\u2014but it has also never been easier to hide malicious behavior within them.&nbsp;<\/p>\n\n\n\n<p>With the rise of large language models, anyone can now generate long and realistic-looking Power Query scripts that include harmful code disguised among seemingly routine steps. These scripts might load a calendar table, sort data, or calculate metrics\u2014while quietly sending data to an unknown website or accessing local files in the background.&nbsp;<\/p>\n\n\n\n<p>What\u2019s especially concerning is that these steps can be hidden in plain sight. Obfuscated code can use misleading step names, redundant transformations, or string concatenation to mask its true purpose. And with AI-generated scripts becoming more common in developer forums and social media, it\u2019s increasingly difficult to tell trusted code from tampered code at a glance.&nbsp;<\/p>\n\n\n\n<p><strong>Stay safe.<\/strong> Don\u2019t assume a script is safe just because it looks professional or comes from a well-meaning source. Always review the steps carefully, especially those involving functions like Web.Contents, Folder.Files, or Execute blocks for Python or R.\u00a0<\/p>\n\n\n\n<p>If you\u2019re unsure what a complex script is doing, it can help to use a tool\u2014or even a language model\u2014to explain the code rather than write it. Asking for a plain-language summary of each step is often enough to uncover suspicious behavior.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>We have a strong community in Power BI, and TMDL View offers a huge benefit to improve your development processes. However, you should be cautious about running TMDL scripts you find online without first inspecting their contents. Doing so will help protect your data and safeguard the community from bad actors.<\/p>\n\n\n\n<p>Did I miss any security considerations? Let me know in the comments.<\/p>\n\n\n\n<p><sup>1<\/sup><em>\u00a0I used\u00a0this simple\u00a0prompt\u00a0in ChatGPT: \u201cPlease obfuscate this Power Query Code denoted by ~~~ and remove comments\u201d.\u00a0<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Explore the benefits and hidden risks of Power BI\u2019s TMDL View. Learn how to safely use TMDL scripts with expert tips on security and best practices.&hellip;<\/p>\n","protected":false},"author":344919,"featured_media":107492,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[159160,159166],"tags":[5528,101611],"coauthors":[159224],"class_list":["post-107465","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-business-intelligence","category-powerbi","tag-business-intelligence","tag-power-bi"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107465","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/344919"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=107465"}],"version-history":[{"count":9,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107465\/revisions"}],"predecessor-version":[{"id":107541,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107465\/revisions\/107541"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/107492"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=107465"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=107465"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=107465"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=107465"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}